Nicer switches for our ESP web server relay project

Hello and welcome to our blog post today, where we continue the topic Webserver on the ESP.



There have been some busy readers who have tried the buttons from our previous contribution to integrate the ESP web server into their code. Unfortunately, no luck.

For someone who has just started programming microcontrollers, and has little or no experience with HTML, and then is additionally flooded with CSS code, this is also very confusing.

If all three are then combined in a text document, it will also become very confusing very quickly.

However, do not be discouraged by this. I'll show you today what the working code with the beautiful buttons looks like. I deliberately refrained from keeping the code compact to make it easier to read.

But you will soon see how expensive the source code can become, even if in the end we only want to change the appearance of two buttons.

So our goal today is to change:

 

 

Here to compare the two sketches:

 

 

As you can easily see, the design of the buttons by CSS alone takes a large part into account. However, most readers had mastered this part.

The part that gives the buttons functionality proved difficult. This was not implemented in the HTML code on the example page for the buttons.
This is probably the case with most templates and examples you will find on the buttons and other elements in the network. Therefore, a brief explanation of how you can implement this on the basis of our original code. As always, there are many solutions that lead to the goal, and the one I have shown is certainly not the simplest or the most elegant.

The buttons we have used so far, if only reduced to the button, can be seen as HTML code as follows:

<a href="/5/on"> <button class="button">EIN</button>

In the example ofhttp://jsfiddle.net/tovic/ve8mU/light/stands as HTML code for a button:

<span class="toggle">
<input type="checkbox">
<label data-off="Stop" data-on="Play"></label>
</span>

So it is not possible to define a link by means of <a> tag, because the whole thing is a checkbox, and this changes the state when you click, but does not communicate with the server. This is because these selection fields are usually used for forms where you fill out a form and end up sending it to the server by clicking on a button (e.g. "Submit").

In order for something to happen immediately when clicking, we must use onclick='window.location.assign()'and specify between the brackets the URL to call:

<span class="toggle">
<input type="checkbox\" onclick='window.location.assign(\"/4/EIN\\")>
<label data-off=\"AUS\" data-on=\\\\"></label>
</span>

And in case the button is on "ONE":

<span class="toggle">
<input type="checkbox\" onclick='window.location.assign(\"/4/AUS\\")'checked> <label data-off=\"AUS\" data-on=\"EIN"></label>
</span>

At the second we set the <input> object still on "checked".

The complete, revised code looks like this:

 

 

/*********
 Rui Santos.
 Complete project details at http://randomnerdtutorials.com  
*********/

// We invite the already familiar WiFi library
'35; includes <ESP8266WiFi.h>

// Here we enter the WLAN name (SSID) and the train key
const char* page     = "HerWLAN";
const char* password = "Autumn";

// We set the web server to Port 80
WiFi server(80);

// A variable to save the HTTP Request
String header;

// Here the current status of the relay is recorded
String output5State = "Autumn";
String output4State = "Autumn";

// The GPIO Pins used
// D1 = GPIO5 and D2 = GPIO4 - just Google "Amica Pinout"
const int output5 = 5;
const int output4 = 4;

void setup() {   Serial.start(115200);   // Define the defined GPIO pins as output...   pinMode(output5, OUTPUT);   pinMode(output4, OUTPUT);   /... and first bet on LOW   digitalWrite(output5, LOW);   digitalWrite(output4, LOW);   // Wireless connection to the network   Serial.print("Connecting to");   Serial.Print(page);   WiFi.start(page, password);   while (WiFi.status() != WL CONNECTED) {     delay(500);     Serial.print(".");   }   // Print the IP from the web server on the serial monitor   Serial.Print("");   Serial.Print("WiFi connected.");   Serial.Print("IP Address:);   Serial.Print(WiFi.localIP());   server.start();
}

void run(){   WiFiClient client = server.available();   // Listens to requests from clients   if (client) {                             // If a new client joins,     Serial.Print("New client.");          // Output to serial monitor     String currentLine = "";                // create a string with the incoming data from the client     while (client.connected()) {            // Repeat as long as the client is connected       if (client.available()) {             // If there is a byte to read,         char c = client.read();             // read the byte, and then         Serial.write(c);                    // display it on the serial monitor         header += c;         if (c == '\n') {                    // if the byte is a new line Char           // when the current line is empty, two followed.           // this is the end of the client's HTTP request, so we send an answer:           if (currentLine.length() == 0) {             // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)             // followed by the content type so the client knows what follows, followed by a blank line:             client.Print("HTTP/1.1 200 OK");             client.Print("Content-type:text/html");             client.Print("Connection: close");             client.Print();                          // Here the GPIO pins are switched on or off             if (header.index("GET /5/ONE") >= 0) {               Serial.Print("GPIO 5 ONE");               output5State = "A";               digitalWrite(output5, HIGH);             } ed if (header.index("GET /5/AUS") >= 0) {               Serial.Print("GPIO 5 AUS");               output5State = "Autumn";               digitalWrite(output5, LOW);             } ed if (header.index("GET /4/ONE") >= 0) {               Serial.Print("GPIO 4 ONE");               output4State = "A";               digitalWrite(output4, HIGH);             } ed if (header.index("GET /4/AUS") >= 0) {               Serial.Print("GPIO 4 OUS");               output4State = "Autumn";               digitalWrite(output4, LOW);             }                          // Here is the HTML page:             client.Print("<? DOCTYPE html><html>");             client.Print("<head> <meta name=\"viewport\"content="width=device-width, initial-scale=1\"> <title>Amica WebServer</title>");             client.Print("<link rel=\"icon\"href=\"data:,\">");                          // Follow the CSS code to configure the on/off buttons                          client.Print("<style> body {");             client.Print("font-family:Helvetica;");             client.Print("background-color:\35; eee;");             client.Print("text-align:center;");             client.Print(padding:85px 0;");             client.Print("}");             client.Print("");             client.Print("toggle {");             client.Print("position:relative;");             client.Print("display:inline-block;");             client.Print("width:80px;");             client.Print("height:120px;");             client.Print("background-color:\35; bbb;");             client.Print("-webkit-border-radius:4px;");             client.Print("moz-border-radius:4px;");             client.Print("border-radius:4px;");             client.Print("text-align:center;");             client.Print("}");             client.Print("");             client.Print("toggle input {");             client.Print("width:100%;");             client.Print("height:100%;");             client.Print(margin:0;");             client.Print(padding:0;");             client.Print("position:absolute;");             client.Print(Top:0;");             client.Print("right:0;");             client.Print("bottom:0;");             client.Print("left:0;");             client.Print("z-index:2;");             client.Print("cursor:pointer;");             client.Print("opacity:0;");             client.Print("filter:alpha(opacity=0);");             client.Print("}");             client.Print("");             client.Print("toggle label {");             client.Print("display:block;");             client.Print("position:absolute;");             client.Print("top:1px;");             client.Print("right:1px;");             client.Print("bottom:1px;");             client.Print("left:1px;");             client.Print("background image:-webkit-linear-gradient(top,\35; fff 0%,\35; ddd 50%,'35; fff 50%,'35;eee 100%);");             client.Print("background-image:-moz-linear-gradient(top,35; fff 0%,'35; ddd 50%,'35; fff 50%,'35;eee 100%);");             client.Print("background-image:-ms-linear-gradient(top,\35; fff 0%,'35; ddd 50%,'35; fff 50%,\35;eee 100%);");             client.Print("background-image:-o-linear-gradient(top,35;fff 0%,'35; ddd 50%,'35; fff 50%,'35;eee 100%);");             client.Print("background-image:linear-gradient(top,\35; fff 0%,\35; ddd 50%,\35; fff 50%,\35; eee 100%);");             client.Print("-webkit-box-shadow:0 2px 3px rgba(0,0,0.4),");             client.Print("Insect 0 -1px 1px \35; 888,");             client.Print("insect 0 -5px 1px \35; bbb,");             client.Print("insect 0 -6px 0 white;");             client.Print("-moz-box-shadow:0 2px 3px rgba(0,0,0.4),");             client.Print("Insect 0 -1px 1px \35; 888,");             client.Print("insect 0 -5px 1px \35; bbb,");             client.Print("insect 0 -6px 0 white;");             client.Print("box-shadow:0 2px 3px rgba(0,0,0.4),");             client.Print("Insect 0 -1px 1px \35; 888,");             client.Print("insect 0 -5px 1px \35; bbb,");             client.Print("insect 0 -6px 0 white;");             client.Print("-webkit-border-radius:3px;");             client.Print("moz-border-radius:3px;");             client.Print("border-radius:3px;");             client.Print("font:normal 11px Arial,Sans-Serif;");             client.Print("Color:'356;666;");             client.Print("text-shadow:0 1px 0 white;");             client.Print("cursor:text;");             client.Print("}");             client.Print("");             client.Print("toggle label:before {");             client.Print("content:attr(data-off);");             client.Print("position:absolute;");             client.Print("top:6px;");             client.Print("right:0;");             client.Print("left:0;");             client.Print("z-index:4;");             client.Print("}");             client.Print("");             client.Print("toggle label:after {");             client.Print("content:attr(data-on);");             client.Print("position:absolute;");             client.Print("right:0;");             client.Print("bottom:11px;");             client.Print("left:0;");             client.Print("Color:'356;666;");             client.Print("text-shadow:0 -1px 0 \35; eee;");             client.Print("}");             client.Print("");             client.Print("toggle input:checked + label {");             client.Print("background image:-webkit-linear-gradient(top,\35; eee 0%,\35; ccc 50%,'35; fff 50%,'35; eee 100%);");             client.Print("background image:-moz-linear-gradient(top,\35; eee 0%,\35; ccc 50%,'35; fff 50%,'35; eee 100%);");             client.Print("background image:-ms-linear-gradient(top,-35; eee 0%,-35; ccc 50%,-35; fff 50%,-35; eee 100%);");             client.Print("background-image:-o-linear-gradient(top,\35; eee 0%,\35; ccc 50%,'35; fff 50%,\35; eee 100%);");             client.Print("background-image:linear-gradient(top,\35; eee 0%,\35; ccc 50%,'35; fff 50%,\35; eee 100%);");             client.Print("-webkit-box-shadow:0 1px rgba(0,0,0.4),");             client.Print("Insect 0 1px 7px -1px \35; ccc,");             client.Print("insect 0 5px 1px \35; fafafa,");             client.Print("insect 0 6px 0 white;");             client.Print("-moz-box-shadow:0 1px rgba(0,0,0.4),");             client.Print("Insect 0 1px 7px -1px \35; ccc,");             client.Print("insect 0 5px 1px \35; fafafa,");             client.Print("insect 0 6px 0 white;");             client.Print("box-shadow:0 1px rgba(0,0,0.4),");             client.Print("Insect 0 1px 7px -1px \35; ccc,");             client.Print("insect 0 5px 1px \35; fafafa,");             client.Print("insect 0 6px 0 white;");             client.Print("}");             client.Print("");             client.Print("toggle input:checked:hover + label {");             client.Print("-webkit-box-shadow:0 1px 3px rgba(0,0,0.4),");             client.Print("Insect 0 1px 7px -1px \35; ccc,");             client.Print("insect 0 5px 1px \35; fafafa,");             client.Print("insect 0 6px 0 white;");             client.Print("-moz-box-shadow:0 1px 3px rgba(0,0,0.4),");             client.Print("Insect 0 1px 7px -1px \35; ccc,");             client.Print("insect 0 5px 1px \35; fafafa,");             client.Print("insect 0 6px 0 white;");             client.Print("box-shadow:0 1px 3px rgba(0,0,0.4),");             client.Print("Insect 0 1px 7px -1px \35; ccc,");             client.Print("insect 0 5px 1px \35; fafafa,");             client.Print("insect 0 6px 0 white;");             client.Print("}");             client.Print("");             client.Print("toggle input:checked + label:before {");             client.Print("z-index:1;");             client.Print("top:11px;");             client.Print("}");             client.Print("");             client.Print("toggle input:checked + label:after {");             client.Print("bottom:9px;");             client.Print("Color:'35;aaa;");             client.Print(text-shadow:none;");             client.Print("z-index:4;");             client.Print("}");             client.Print("</style></head>");                                      // Websites             client.Print("<body><h1>ESP8266 Web Server</h1>");                                                       // Show the current status, and ONE/AUS buttons for GPIO 5             client.Print("<p> + output5State + "</p>");             // if output5State = AUS, show ONE button             if (output5State=="Autumn") {               client.Print("<p><span class=\"toggle"><input type=\"checkbox\"onclick='window.location.assign(\\"/5/EIN\\\")'> <label data-off=\"AUS\"data-on=\"EIN"></label></p>");             } ed {               client.Print("<p><span class=\"toggle"><input type=\"checkbox\"onclick='window.location.assign(\\"/5/AUS\\\")'checked><label data-off=\\"AUS\"data-on=\\"EIN"></label></p>");             }                             // The same for GPIO 4             client.Print("<p> + output4State + "</p>");             // When output4State = off, show the ONE button             if (output4State=="Autumn") {               client.Print("<p><span class=\"toggle"><input type=\"checkbox\"onclick='window.location.assign(\"/4/EIN\\\")'> <label data-off=\"AUS\"data-on=\"EIN"></label></p>");             } ed {               client.Print("<p><span class=\"toggle"><input type=\"checkbox\"onclick='window.location.assign(\"/4/AUS\\")'checked><label data-off=\\"AUS\"data-on=\\"EIN"></label></p>");             }             client.Print("</body></html>");                          // The HTTP response ends with a blank line             client.Print();             // and we leave the loop with a break             break;           } ed { // if a new line comes, delete the current line             currentLine = "";           }         } ed if (c != '\r') {  // when something comes that is not a line breaker,           currentLine += c;      // add it at the end of currentLine         }       }     }     // Delete the header variable for the next pass     header = "";     // Close the connection     client.stop();     Serial.Print("Client separated.");     Serial.Print("");   }
}

 

Now one more question remains: why do we use /4/EIN or /5/AUS in our code to switch on the GPIOs?

In this way, it is possible to put a desired relay into the desired state by entering the IP followed by /"pin number"/"status".

But the request does not necessarily have to come from a web browser. If you have another device in your WLAN, such as another ESP, it could switch the desired relay with a simple HTTP request. You could hang a light switch on this second ESP. Or a motion detector.

Or you could write an app for your smartphone with buttons that don't make anything colder than calling the desired URL.

Of course, I must not neglect the issue of security at this point.

The ESP server is accessible for every participant in their WLAN and there is no security request. So it's only as safe as your Wi-Fi. If you give friends or relatives their key, or if your WLAN router is incorrectly configured, or if there is a security gap, theoretically anyone can switch the relay on.

For a light switch or similar, this should not be the big problem, but before you start to control door locks and garage doors, I strongly recommend that you address the issue of network security.

 

I hope you enjoyed today's contribution and showed that it is not so complicated to include the ESP in your projects, even if the implementation initially seems very complicated.

I'll say goodbye to my next post, and I'm glad to hear your praise and criticism.

Your Markus Neumann

 

Esp-32Projects for advanced

7 comments

Josef Bernhardt

Josef Bernhardt

Gratuliere zu dem tollen Programm
Ich werde die Software evtl. für mein ESP8266 E/A Modul benutzen.
https://www.linkedin.com/feed/update/urn:li:activity:6706839832758497281/

Günther

Günther

Hallo, Super Beispiel welches ich auch gerne als Vorlage für mein Projekt verwende. Hier wäre der nächste Schritt die HTML Seite mit css und js in den ESP Speicher zu verfrachten um mehr Übersicht zu schaffen. Bin aber selbst noch nicht durch.
Danke für die Beispiele.

Andreas

Andreas

Danke für die tollen Artikel, damit macht es auch Leien wie mir einfach nur Spaß soetwas nachzubauen!
Und wenn das kein Argument ist die Hardware bei euch zu kaufen, dann weis ich auch nicht!!!
Bitte weiter so !!!!!
DANKE

Andreas

Andreas

Danke für die tollen Artikel, damit macht es auch Leien wie mir einfach nur Spaß soetwas nachzubauen!
Und wenn das kein Argument ist die Hardware bei euch zu kaufen, dann weis ich auch nicht!!!
Bitte weiter so !!!!!
DANKE

Jo

Jo

Super Beitrag, vielen Dank!!!!
Gehöre zu der Laien-Truppe, die bisher immer an der Problematik “Button-Funktionalität” gescheitert ist. Jetzt funzt es … Nochmals Danke …

Rainer

Rainer

hat super geklappt,
wie mache ich das mit 6 Schalter ?
Grüsse

Mike

Mike

Sieht einfach gut aus, wills mal probieren

Leave a comment

All comments are moderated before being published

Recommended blog posts

  1. Install ESP32 now from the board manager
  2. Lüftersteuerung Raspberry Pi
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1
  4. ESP32 - das Multitalent
  5. OTA - Over the Air - ESP programming via WLAN