Issues controlling ESP-01 programmed with Arduino IDE from web browser

Hello,

This is my first project with the ESP8266 (ESP-01) so i tried to comment the code a lot, mostly for my own understanding. Any feedback for improvement is most welcome. I am using the Arduno IDE to program it. I have the code working to control ESP-01 GPIO pin 2 to activate/deactivate a connected relay. I can access and change the relay status from the IP address in a web browser, but there are some issues:

  1. I get compilation errors with the following lines: client.println(""); and client.println("");
    Error:
expected ')' before 'en'

How to print these HTML codes?

  1. There is a need for a new line before DOCTYPE HTML. My vague guess is that it is part of some sort of internet server standard protocol??
client.println(""); // need to have a space here for response
client.println("<!DOCTYPE HTML>");
  1. I had to comment out client.stop(); as the browser page shows the following error: “The connection was reset” and only the following worked and i do not understand why: Serial.println(“Client disconnected”);

The full code running on the ESP-01:

#include <ESP8266WiFi.h>

const char* ssid = "*****"; // enter SSID
const char* password = "******";  // enter password

int relayPin = 2; // GPIO2 of ESP-01
int relay_status = LOW;  // status of relay initialised to LOW/OFF
WiFiServer ESPserver(80); //Service Port

void setup() 
{
Serial.begin(115200);
pinMode(relayPin, OUTPUT);
digitalWrite(relayPin, LOW);
 
Serial.println();
Serial.println();
Serial.print("Connecting to SSID: ");
Serial.println(ssid);
 
WiFi.begin(ssid, password);
delay(5000);

// These four lines of code assign static IP address to ESP-01. Otherwise, comment out to get automatic IP.
// IPAddress ip(192,168,8,233);
// IPAddress gateway(192,168,1,1);
// IPAddress subnet(255,255,255,0);
// WiFi.config(ip, gateway, subnet);

delay(5000);
 
while (WiFi.status() != WL_CONNECTED) 
{
  delay(100);
  Serial.print("*");
}
Serial.println("");
Serial.println("WiFi connected");
 
// Start the server
ESPserver.begin();
Serial.println("Server started");
 
// Print the IP address
Serial.print("The URL to control ESP-01: ");
Serial.print("http://");
Serial.println(WiFi.localIP());
Serial.println("");
}

void loop() 
{
// Check if a client has connected
WiFiClient client = ESPserver.available();
if (!client) 
{
  return;
}

// Wait until the client sends some data
Serial.println("Client connected");
while(!client.available())
{
  delay(1);
}

// Read the first line of the request
String request = client.readStringUntil('\r');
Serial.println(request);
client.flush();

// Match the request
if (request.indexOf("/RELAYON") != -1) 
{
  Serial.println("Relay is ON");
  digitalWrite(relayPin, HIGH);
  relay_status = LOW;
}
if (request.indexOf("/RELAYOFF") != -1)
{
  Serial.println("Relay is OFF");
  digitalWrite(relayPin, LOW);
  relay_status = HIGH;
}

// Return the response
// send a standard http response header
client.println("HTTP/1.1 200 OK");  // start the web response that is sent to the web browser
// The 200 OK is a HTTP response code and in this case is 200 which means the request is OK
client.println("Content-Type: text/html");  // tell the browser that the response content type is text/html
client.println("Connection: close");
// the connection will be closed after completion of the response
client.println(""); // need to have a space here for response
client.println("<!DOCTYPE HTML>");
//client.println("<html lang="en">"); 
client.println("<html>");
client.println("<head>");
//client.println("<meta charset='utf-8'>");
//client.println("<meta charset="utf-8">");
client.println("<title>Control relay via ESP-01 on local network</title>");
client.println("</head>");
client.println("<body>");
client.println("<h2>Control relay via ESP-01 on local network</h2>");
// Prints in the computer browser
client.print("<p>Status of the relay: ");

if(relay_status == LOW)
{
  client.println("ON</p>");
}
else
{
  client.println("OFF</p>");
}

client.println("</body>");
client.println("</html>");

// give the web browser time to receive the data
delay(1);

// close the connection:
//client.stop();
Serial.println("Client disconnected");
Serial.println("");
}
 client.println("<html lang="en">"); and client.println("<meta charset="utf-8">");

If you need to have quotation marks in what you send you need to escape them

An example

void setup()
{
  Serial.begin(115200);
  while (!Serial);
  Serial.println("example of \"quotation\" marks in text");
}

void loop()
{
}
  1. use " for " inside a string
  2. empty line is required, but not before DOCTYPE but after the HTTP response headers (same place). println() is good, no need for ""

client.flush() changed some years ago in Arduino from 'eat' the input to flush the output as usual in C, C++, Java etc.
so it doesn't read the rest of the request.
browsers don't like to get the response before they finished to send the request. they abort

OK, i have changed code according to your advice:

#include <ESP8266WiFi.h>

const char* ssid = "*****"; // enter Service Set Identifier
const char* password = "*****";  // enter WiFi network password

int relayPin = 2; // GPIO2 of ESP-01
int relay_status = LOW;  // status of relay initialised to LOW
WiFiServer ESPserver(80); //Service Port

void setup() 
{
Serial.begin(115200); //Default Baud Rate for ESP-01
pinMode(relayPin, OUTPUT);  // Connect relay to ESP-01's GPIO 2
digitalWrite(relayPin, LOW);  // set initial status to LOW
 
Serial.println();
Serial.println();
Serial.print("Connecting to WiFi: ");
Serial.println(ssid);
 
WiFi.begin(ssid, password);
delay(5000);

// The following 5 lines of code assign static IP address to ESP-01. Otherwise, comment out to get automatic IP.
// IPAddress ip(192,168,8,233);
// IPAddress gateway(192,168,1,1);
// IPAddress subnet(255,255,255,0);
// WiFi.config(ip, gateway, subnet);
//delay(5000);
 
while (WiFi.status() != WL_CONNECTED) 
{
  delay(100);
  Serial.print("*");
}
Serial.println("");
Serial.println("WiFi connected");
 
// Start the server
ESPserver.begin();
Serial.println("Server started");
 
// Print the IP address
Serial.print("The URL to control ESP-01: ");
Serial.print("http://");
Serial.println(WiFi.localIP());
Serial.println("");
}

void loop() 
{
// Check if a client has connected
WiFiClient client = ESPserver.available();
if (!client) 
{
  return;
}

// Wait until the client sends some data
Serial.println("Client connected");
while(!client.available())
{
  delay(1);
}

// Read the first line of the request
String request = client.readStringUntil('\r');
Serial.println(request);
client.flush();

// Match the request
if (request.indexOf("/RELAYON") != -1) 
{
  Serial.println("Relay is ON");
  digitalWrite(relayPin, HIGH);
  relay_status = LOW;
}
else if (request.indexOf("/RELAYOFF") != -1)
{
  Serial.println("Relay is OFF");
  digitalWrite(relayPin, LOW);
  relay_status = HIGH;
}
else 
{
  Serial.println("Invalid request");
  //client.stop();
  Serial.println("Client disconnected");
  Serial.println();
  return;
}

// Send a standard http response header
client.println("HTTP/1.1 200 OK");  // start the web response that is sent to the web browser
// The 200 OK is a HTTP response code and in this case is 200 which means the request is OK
client.println(); // need to have a space here after http response header
client.println("Content-Type: text/html");  // tell the browser that the response content type is text/html
client.println("Connection: close");
// the connection will be closed after completion of the response

client.println("<!DOCTYPE HTML>");  // HTML web site template
client.println("<html lang=\"en\">");
client.println("<head>");
client.println("<meta charset=\"utf-8\">");
client.println("<title>Control relay via ESP-01 on local network</title>");
client.println("</head>");
client.println("<body>");
// Prints the following text in the web browser
client.println("<h2>Control relay via ESP-01 on local network</h2>");
client.print("<p>Status of the relay: ");

if(relay_status == LOW)
{
  client.println("ON</p>");
}
else
{
  client.println("OFF</p>");
}

client.println("</body>");
client.println("</html>");

// give the web browser time to receive the data
delay(1);

// close the connection:
//client.stop();
Serial.println("Client disconnected");
Serial.println();
}
  1. The first issue replacing with " seems to be resolved.

  2. However, now when i load the ESP-01 IP in the web browser, it displays this code instead of the website itself:

Content-Type: text/html
Connection: close
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Control relay via ESP-01 on local network</title>
</head>
<body>
<h2>Control relay via ESP-01 on local network</h2>
<p>Status of the relay: OFF</p>
</body>
</html>
  1. Juraj, i’m not sure what you mean with client.flush()? From what i can see (noob vision), this seems to be working. The issue appears to be with client.stop()?
    I also made this change, where i commented out client.stop() and add the next 2 lines:
else
{
 Serial.println("Invalid request");
 //client.stop();
 Serial.println("Client disconnected");
 Serial.println();
 return;
}

the HTTP headers are

Content-Type: text/html
Connection: close

so the empty line terminating them should be after them

the ESP8266WiFi library stops the client as it is destroyed at the end of loop()

OK, the web page is displaying correctly but i am trying to add an error message if the address suffix is neither RELAYON nor RELAYOFF. So, if i type the ESP IP followed by any other text, it should display an error message: Invalid request.
But for some reason, it does not work. I get the same web page as RELAYON.

This is the current code:

#include <ESP8266WiFi.h>

const char* ssid = "*****"; // enter Service Set Identifier
const char* password = "*****";  // enter WiFi network password

int relayPin = 2; // GPIO2 of ESP-01
int relay_status = LOW;  // status of relay initialised to LOW
WiFiServer ESPserver(80); //Service Port

void setup() 
{
Serial.begin(115200); //Default Baud Rate for ESP-01
pinMode(relayPin, OUTPUT);  // Connect relay to ESP-01's GPIO 2
digitalWrite(relayPin, LOW);  // set initial status to LOW
 
Serial.println();
Serial.println();
Serial.print("Connecting to WiFi: ");
Serial.println(ssid);
 
WiFi.begin(ssid, password);
delay(5000);

// The following 5 lines of code assign static IP address to ESP-01. Otherwise, comment out to get automatic IP.
// IPAddress ip(192,168,8,233);
// IPAddress gateway(192,168,1,1);
// IPAddress subnet(255,255,255,0);
// WiFi.config(ip, gateway, subnet);
//delay(5000);
 
while (WiFi.status() != WL_CONNECTED) 
{
  delay(100);
  Serial.print("*");
}
Serial.println("");
Serial.println("WiFi connected");
 
// Start the server
ESPserver.begin();
Serial.println("Server started");
 
// Print the IP address
Serial.print("The URL to control ESP-01: ");
Serial.print("http://");
Serial.println(WiFi.localIP());
Serial.println("");
}

void loop() 
{
// Check if a client has connected
WiFiClient client = ESPserver.available();
if (!client) 
{
  return;
}

// Wait until the client sends some data
Serial.println("Client connected");
while(!client.available())
{
  delay(1);
}

// Read the first line of the request
String request = client.readStringUntil('\r');
Serial.println(request);
client.flush();

// Match the request
if (request.indexOf("/RELAYON") != -1) 
{
  Serial.println("Relay is ON");
  digitalWrite(relayPin, HIGH);
  relay_status = LOW;
}
else if (request.indexOf("/RELAYOFF") != -1)
{
  Serial.println("Relay is OFF");
  digitalWrite(relayPin, LOW);
  relay_status = HIGH;
}
else 
{
  Serial.println("Invalid request");
  //client.stop();
  //Serial.println("Client disconnected");
  //Serial.println();
  //return;
}

// Send a standard http response header
client.println("HTTP/1.1 200 OK");  // start the web response that is sent to the web browser
// The 200 OK is a HTTP response code and in this case is 200 which means the request is OK

client.println("Content-Type: text/html");  // tell the browser that the response content type is text/html
client.println("Connection: close");
// the connection will be closed after completion of the response
client.println(); // need to have a space here after http response header

client.println("<!DOCTYPE HTML>");  // HTML web site template
client.println("<html lang=\"en\">");
client.println("<head>");
client.println("<meta charset=\"utf-8\">");
client.println("<title>Control relay via ESP-01 on local network</title>");
client.println("</head>");
client.println("<body>");
// Prints the following text in the web browser
client.println("<h2>Control relay via ESP-01 on local network</h2>");
client.print("<p>Status of the relay: ");

if(relay_status == LOW)
{
  client.println("ON</p>");
}
else
{
  client.println("OFF</p>");
}

client.println("</body>");
client.println("</html>");

// give the web browser time to receive the data
delay(1);

// close the connection:
//client.stop();
Serial.println("Client disconnected");
Serial.println();
}

I think it has to do with this section:

// Match the request
if (request.indexOf("/RELAYON") != -1) 
{
  Serial.println("Relay is ON");
  digitalWrite(relayPin, HIGH);
  relay_status = LOW;
}
else if (request.indexOf("/RELAYOFF") != -1)
{
  Serial.println("Relay is OFF");
  digitalWrite(relayPin, LOW);
  relay_status = HIGH;
}
else 
{
  Serial.println("Invalid request");
  //client.stop();
  //Serial.println("Client disconnected");
  //Serial.println();
  //return;
}

I’m not sure what to change in terms of logical expression to display the error message about invalid request. Is this correct??

else if (request.indexOf("/RELAYOFF") == -1)
{
  Serial.println("Invalid request");
  //client.stop();
  //Serial.println("Client disconnected");
  //Serial.println();
  //return;
}

you figure it out :slight_smile:

“If you need to have quotation marks in what you send you need to escape them”

As a quick tip, instead of escaping the " in the html code with , you can also use ’ instead of " like below and the html should still work. In the raw html code one can do a find " and replace with ’ to make the task quick and the html still generally easily readable afterwards.

client.println("<H1>Zoomkat's simple Arduino button</H1>");

client.println("<a href='/?on1' target='inlineframe'>ON</a>");
client.println("<a href='/?off' target='inlineframe'>OFF</a>");
client.println("<a href='/data' target='DataBox'>DATA</a>
");

client.print("<iframe src='/data' width='350' height='250' name='DataBox'>");
client.print("</iframe>");

client.println("<IFRAME name=inlineframe style='display:none'>");
client.println("</IFRAME>");

client.println("</BODY>");
client.println("</HTML>");

Juraj:
you figure it out :slight_smile:

I did it. Thanks for the vote of confidence. :slight_smile:

Here is the fixed code:

#include <ESP8266WiFi.h>

const char* ssid = "*****"; // enter Service Set Identifier
const char* password = "*****";  // enter WiFi network password

int relayPin = 2; // GPIO2 of ESP-01
int relay_status = 0;  // status of relay initialised to 0 or OFF.
WiFiServer ESPserver(80); //Service Port

void setup() 
{
Serial.begin(115200); //Default Baud Rate for ESP-01
pinMode(relayPin, OUTPUT);  // Connect relay to ESP-01's GPIO 2
digitalWrite(relayPin, LOW);  // set initial status to LOW
 
Serial.println();
Serial.println();
Serial.print("Connecting to WiFi: ");
Serial.println(ssid);
 
WiFi.begin(ssid, password);
delay(5000);

// The following 5 lines of code assign static IP address to ESP-01. Otherwise, comment out to get automatic IP.
// IPAddress ip(192,168,8,233);
// IPAddress gateway(192,168,1,1);
// IPAddress subnet(255,255,255,0);
// WiFi.config(ip, gateway, subnet);
//delay(5000);
 
while (WiFi.status() != WL_CONNECTED) 
{
  delay(100);
  Serial.print("*");
}
Serial.println("");
Serial.println("WiFi connected");
 
// Start the server
ESPserver.begin();
Serial.println("Server started");
 
// Print the IP address
Serial.print("The URL to control ESP-01: ");
Serial.print("http://");
Serial.println(WiFi.localIP());
Serial.println("");
}

void loop() 
{
// Check if a client has connected
WiFiClient client = ESPserver.available();
if (!client) 
{
  return;
}

// Wait until the client sends some data
Serial.println("Client connected");
while(!client.available())
{
  delay(1);
}

// Read the first line of the request
String request = client.readStringUntil('\r');
Serial.println(request);
client.flush();

// Match the request
if (request.indexOf("/RELAYON") != -1)
{
  Serial.println("Relay is ON");
  digitalWrite(relayPin, HIGH);
  relay_status = 0; // OFF
}
else if (request.indexOf("/RELAYOFF") != -1)
{
  Serial.println("Relay is OFF");
  digitalWrite(relayPin, LOW);
  relay_status = 1; // ON
}
else
{
  Serial.println("Invalid request");
  relay_status = 2; // Invalid request
  //client.stop();
  //Serial.println("Client disconnected");
  //Serial.println();
  //return;
}

// Send a standard http response header
client.println("HTTP/1.1 200 OK");  // start the web response that is sent to the web browser
// The 200 OK is a HTTP response code and in this case is 200 which means the request is OK

client.println("Content-Type: text/html");  // tell the browser that the response content type is text/html
client.println("Connection: close");
// the connection will be closed after completion of the response
client.println(); // need to have a space here after http response header

client.println("<!DOCTYPE HTML>");  // HTML web site template
client.println("<html lang=\"en\">");
client.println("<head>");
client.println("<meta charset=\"utf-8\">");
client.println("<title>Control relay via ESP-01 on local network</title>");
client.println("</head>");
client.println("<body>");
// Prints the following text in the web browser
client.println("<h2>Control relay via ESP-01 on local network</h2>");
client.print("<p>Status of the relay: ");

if (relay_status == 0)
{
  client.println("ON</p>");
}
else if (relay_status == 1)
{
  client.println("OFF</p>");
}
else if (relay_status == 2)
{
  client.println("Invalid request</p>");
}

client.println("</body>");
client.println("</html>");

// give the web browser time to receive the data
delay(1);

// close the connection:
//client.stop();
Serial.println("Client disconnected");
Serial.println();
}

zoomkat:
“If you need to have quotation marks in what you send you need to escape them”

As a quick tip, instead of escaping the " in the html code with , you can also use ’ instead of " like below and the html should still work. In the raw html code one can do a find " and replace with ’ to make the task quick and the html still generally easily readable afterwards.

client.println("<H1>Zoomkat's simple Arduino button</H1>");

client.println(“ON”);
client.println(“OFF”);
client.println("DATA
");

client.print("");

client.println("");

client.println("");
client.println("");

Thanks for the tip. I don’t know how to use iframe (i’m HTML noob), but incorporated some of it as a controller with clickable buttons. Awesome! :slight_smile:

#include <ESP8266WiFi.h>

const char* ssid = "*****"; // enter Service Set Identifier
const char* password = "*****";  // enter WiFi network password

int relayPin = 2; // GPIO2 of ESP-01
int relay_status = 0;  // status of relay initialised to 0 or OFF.
WiFiServer ESPserver(80); //Service Port

void setup() 
{
Serial.begin(115200); //Default Baud Rate for ESP-01
pinMode(relayPin, OUTPUT);  // Connect relay to ESP-01's GPIO 2
digitalWrite(relayPin, LOW);  // set initial status to LOW
 
Serial.println();
Serial.println();
Serial.print("Connecting to WiFi: ");
Serial.println(ssid);
 
WiFi.begin(ssid, password);
delay(5000);

// The following 5 lines of code assign static IP address to ESP-01. Otherwise, comment out to get automatic IP.
// IPAddress ip(192,168,8,233);
// IPAddress gateway(192,168,1,1);
// IPAddress subnet(255,255,255,0);
// WiFi.config(ip, gateway, subnet);
//delay(5000);
 
while (WiFi.status() != WL_CONNECTED) 
{
  delay(100);
  Serial.print("*");
}
Serial.println("");
Serial.println("WiFi connected");
 
// Start the server
ESPserver.begin();
Serial.println("Server started");
 
// Print the IP address
Serial.print("The URL to control ESP-01: ");
Serial.print("http://");
Serial.println(WiFi.localIP());
Serial.println("");
}

void loop() 
{
// Check if a client has connected
WiFiClient client = ESPserver.available();
if (!client) 
{
  return;
}

// Wait until the client sends some data
Serial.println("Client connected");
while(!client.available())
{
  delay(1);
}

// Read the first line of the request
String request = client.readStringUntil('\r');
Serial.println(request);
client.flush();

// Match the request
if (request.indexOf("/RELAYON") != -1)
{
  Serial.println("Relay is ON");
  digitalWrite(relayPin, HIGH);
  relay_status = 0; // OFF
}
else if (request.indexOf("/RELAYOFF") != -1)
{
  Serial.println("Relay is OFF");
  digitalWrite(relayPin, LOW);
  relay_status = 1; // ON
}
else
{
  Serial.println("Invalid request");
  relay_status = 2; // Invalid request
  //client.stop();
  //Serial.println("Client disconnected");
  //Serial.println();
  //return;
}

// Send a standard http response header
client.println("HTTP/1.1 200 OK");  // start the web response that is sent to the web browser
// The 200 OK is a HTTP response code and in this case is 200 which means the request is OK

client.println("Content-Type: text/html");  // tell the browser that the response content type is text/html
client.println("Connection: close");
// the connection will be closed after completion of the response
client.println(); // need to have a space here after http response header

client.println("<!DOCTYPE HTML>");  // HTML web site template
client.println("<html lang=\"en\">");
client.println("<head>");
client.println("<meta charset=\"utf-8\">");
client.println("<title>Control relay via ESP-01 on local network</title>");
client.println("</head>");
client.println("<body>");
// Prints the following text in the web browser

client.println("<h2>Control relay via ESP-01 on local network</h2>");
client.print("<p>Control relay: ");
client.println("<a href='/RELAYON' target='_self'>ON</a>");
client.println("<a href='/RELAYOFF' target='_self'>OFF</a></p>");

client.print("<p>Status of the relay: ");

if (relay_status == 0)
{
  client.println("<b>ON</b></p>");
}
else if (relay_status == 1)
{
  client.println("<b>OFF</b></p>");
}
else if (relay_status == 2)
{
  client.println("Invalid request</p>");
}

client.println("</body>");
client.println("</html>");

// give the web browser time to receive the data
delay(1);

// close the connection:
//client.stop();
Serial.println("Client disconnected");
Serial.println();
}