DIY: Smarte Verdunkelung - Webserver - Teil 3 - AZ-Delivery

In previous part A button for manual control has already been integrated to enable basic operation of the system. Now, the control system is to be expanded to include additional options.

In this section, the existing structure is supplemented by an integrated web server, which allows the system's functions to be conveniently operated in the local network via a browser.

software

1 web server

Previously, the opening and closing times were hardcoded in the program, meaning that in order to adjust them, the entire code had to be reloaded onto the microcontroller via USB. The web server is intended to remedy this situation by means of an HTML form.

 

The following HTML file provides input options for times and buttons for control:

<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      
<title>Rolladen Zeitsteuerung</title>
     
      
<style>
        
body {
          
font-family: Arial, sans-serif;
          
padding20px;
        }
        
.grid-container {
          
display: grid;
          
grid-template-columns170px 70px;
          
gap100px;
          
align-items: start;
        }
        
.form-block {
          
display: grid;
          
flex-direction: column;
          
gap10px
        }
        
input[type="time"] {
          
font-size1.2em;
          
padding5px;
        }
        
input[type="submit"] {
          
font-size1.2em;
          
padding10px;
          
cursor: pointer;
        }
        
.time-input-container {
          
display: flex;
          
flex-direction: column;
        }
        
.time-input-container label {
          
margin-bottom5px;
        }
        
.time-input-container input {
          
margin-bottom20px;
        }
      
</style>
    
</head>

    
<body>
      
<h2>Rolladen Zeitsteuerung</h2>
      
<div class="grid-container">
        
<div class="form-block">
          
<form action="file:///setTime" method="GET">
            
<div class="time-input-container">
                
<label>Öffnen:   </label>
                
<input type="time" name="time1" value="20" required="">
            
</div>
           
            
<div class="time-input-container">
                
<label>Schließen:</label>
                
<input type="time" name="time2" value="required">
            
</div>
           
            
<input type="submit" value="Uhrzeit speichern">
          
</form>
        
</div>
        
<div class="form-block">
          
<form action="/button1" method="POST">
            
<button type="submit" style="height:50px; width:50px;">&#8613;</button> <!-- Pfeil nach oben -->
          
</form>
          
<form action="/button2" method="POST">
            
<button type="submit" style="height:50px; width:50px;">&#8615; </button>
          
</form>
        
</div>
      
</div>
   
   
</body></html>

 

 

You can download the HTML file here Download and unzip the file, then open it in your browser to view the final version. We recommend using Google Chrome, Firefox, or a Chrome-based browser.

 

Explanation:

In head contains the CSS commands for styling the page, which mainly covers the arrangement of elements. Instructions on how to use these commands to customize the appearance of the website can be found, for example, at here in the Mozilla developer documentation.

 

Under .grid-container can be used with grid-template-columns the width of the columns in the container, and thus the Width of the time input column and button column, can be set.

The parameter gap put the distance between the two columns.

 

With gap under .form-block can the vertical distance between the control buttons.

 

With the two CSS attribute selectors, the text size and the Distance to the edges of the block.

 

With .time-input-container label or input be able to Spacing between elements be set in the time configuration.

 

To adjust the parameters live, we recommend using the browser's developer console. You can easily access this using the keyboard shortcut Ctrl+Shift+I call up.

Figure 1: Website with developer tool open

 

The body of the HTML code contains the logic of the three forms. The server's response when the submit button is pressed looks like this:
/setTime?time1=7:56&time2=21:56

 

 

The two set times can be read from this:

time1: 7:56

time2: 9:56 p.m.

 

These can later be read and processed by the microcontroller.

2 microcontrollers

The microcontroller requires so-called callback methods, which are called when the URL is changed, i.e., when one of the three buttons is pressed:

 

 

void handleRoot() {
 
  
String html = R"rawliteral(
    <!DOCTYPE html>
    <html><head><meta http-equiv="
Content-Type" content="text/html; charset=UTF-8">
      <title>Rolladen Zeitsteuerung</title>
     
      <style>
        body {
          font-family: Arial, sans-serif;
          padding: 20px;
        }
        .grid-container {
          display: grid;
          grid-template-columns: 230px 30px;
          gap: 100px;
          align-items: start;
        }
        .form-block {
          display: grid;
          flex-direction: column;
          gap: 30px
        }
        input[type="
time"] {
          font-size: 1.2em;
          padding: 5px;
        }
        input[type="
submit"] {
          font-size: 1.2em;
          padding: 10px;
          cursor: pointer;
        }
        .time-input-container {
          display: flex;
          flex-direction: column;
        }
        .time-input-container label {
          margin-bottom: 5px;
        }
        .time-input-container input {
          margin-bottom: 15px;
        }
      </style>
    </head>

    <body>
      <h2>Rolladen Zeitsteuerung</h2>
      <div class="
grid-container">
       
        <form action="
/setTime" method="GET">
          <div class=
"time-input-container">
              <label>Öffnen:   </label>
              <input type=
"time" name="time1" value=")rawliteral" + time1 + R"rawliteral(" required="">
          </div>
         
          <div class=
"time-input-container">
              <label>Schließen:</label>
              <input type=
"time" name="time2" value=")rawliteral" + time2 + R"rawliteral(" required="">
          </div>
          <input type=
"submit" value="Uhrzeit speichern">
        </form>
       
        <div class=
"form-block">
          <form action=
"/button1" method="POST">
            <button type=
"submit" style="height:50px; width:50px;">&#8613;</button> <!-- Pfeil nach oben -->
          </form>
          <form action=
"/button2" method="POST">
            <button type=
"submit" style="height:50px; width:50px;">&#8615; </button> <!-- Pfeil nach unten -->

          </form>
        </div>
      </div>
    </body></html>
  )rawliteral
";

  
server.send(200"text/html", html);
}

Explanation:

The default values for the time were set in the HTML using the stored values. This is achieved by inserting the strings time1 and time2.


void convertTime(struct tm* TM, String time) {
  
String temp;
  
int index = time.indexOf(":");
  temp = time.substring(
0, index);
  TM->tm_hour = temp.toInt();
  temp = time.substring(index + 
1);
  TM->tm_min = temp.toInt();
}

 

Explanation:

The helper method reads the time from a string in HH:MM format and writes it to the pointer passed via pointer. tm Structure. 


void handleSetTime() { 
  
if (server.hasArg("time1")) {
    time1 = server.arg(
"time1");
    
Serial.println(time1);
    convertTime(&tOpen, time1);
  }
  
if (server.hasArg("time2")) {
    time2 = server.arg(
"time2");
    
Serial.println(time2);
    convertTime(&tClose, time2);
  }

  prefs.
begin("time");
  prefs.putString(
"open", time1);
  prefs.putString(
"close", time2);
  prefs.
end();

  server.sendHeader(
"Location""/");
  server.send(
303);
}

 

Explanation:

This callback method is called when the new time has been set and the address has been changed to /setTime using the submit button.

The transferred parameters are available as a string. These are then converted into the parameters of the tm structs using the convertTime() function.

The two times are then stored in the ESP32's memory so that they can be retrieved when the device is switched on again.

Finally, the server is reset to the default header.

void handleButton1() {
  
Serial.println("Button 1 gedrückt");
  abrollen(
0);
  server.sendHeader(
"Location""/");
  server.send(
303);
}

void handleButton2() {
  
Serial.println("Button 2 gedrückt");
  abrollen(targetPosition);
  server.sendHeader(
"Location""/");
  server.send(
303);
}

 

Explanation:

These methods are called when one of the two control buttons is pressed. Depending on whether the open or close button was pressed, the corresponding target position is set in the scroll() method.

The loop() and setup() sections were not listed above. These sections only contain the server configuration, such as the callback methods, and in loop() a repeating routine to update the server.


Here you can download the complete code. It contains all object constructors and the configuration in setup().

Furthermore, the roll-off method was modified so that when the stepper motor driver is switched off, the servo motor is also deactivated, as otherwise it would continuously move toward the target position, leading to increased power consumption and noise.


To open the server in your browser, simply enter the IP address of the ESP in the browser.
The IP address is displayed in the serial monitor in setup(), but can also be determined via your router's configuration page.

 

Conclusion

The integration of the web server now provides a convenient option for local operation. The next step is to enable control not only locally, but also across systems – through the integration of the MQTT protocol, which allows easy connection to smart home platforms such as Home Assistant or OpenHAB.


Have fun recreating it :)

Leave a comment

All comments are moderated before being published

Recommended blog posts

  1. ESP32 jetzt über den Boardverwalter installieren - AZ-Delivery
  2. Internet-Radio mit dem ESP32 - UPDATE - AZ-Delivery
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1 - AZ-Delivery
  4. ESP32 - das Multitalent - AZ-Delivery