NodeMCU ESP8266: help with timed button

Hello, this is my first project written in the Arduino IDE. The hardware is a NodeMCU ESP8266 board and what I believe to be a knockoff version of the SEEED Relay Shield v3.0. I based most of the code off examples I have found online, but the issue I am having, is this: I need the "drain" button to only stay open for 5 seconds after being triggered. The code below does work, however I have hit a snag which I am not sure how to solve. The while loop runs perfectly and closes the valve after the required time. However, if the web client is left active in a web browser, as soon as the loop finishes, the browser refreshes and send the button command again. This repeats until I manually force the browser to stop or simply close the tab.

If anyone can help me find a way to get this loop to only run once after the web browser button is pushed, it would be sincerely appreciated. Thank you for taking the time to look over my code.

Sincerely,
Jason

#include <ESP8266WiFi.h>
#include "secret.h"


char ssid[] = SECRET_SSID;
char password[] = SECRET_PASS;

// Set your Static IP address
IPAddress local_IP(192, 168, 1, 123);
// Set your Gateway IP address
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(8, 8, 8, 8);   //optional
IPAddress secondaryDNS(8, 8, 4, 4); //optional
WiFiServer server(80);

//Variable to store HTTP request
String header;

//Auxilliary variable so store the current output state
String compressorState = "off";
String drainState = "closed";
String airSupply1State = "off";
String airSupply2State = "off";

// Assign output variables to GPIO pins
const int compressor = 16; // GPIO16
const int drain = 5; //GPIO05
const int airSupply1 = 4; //GPIO4
const int airSupply2 = 0; //GPIO0

//Current Time
unsigned long currentTime = millis();

//Previous time
unsigned long previousTime = 0;

//Define timeout time in milliseconds
const long timeoutTime = 2000;

//drain timer
static unsigned long drainTime = 0;
static unsigned long drainTimeState = LOW;

void setup() {
  Serial.begin(115200);
  delay(10);
  pinMode(compressor, OUTPUT);
  pinMode(drain, OUTPUT);
  pinMode(airSupply1, OUTPUT);
  pinMode(airSupply2, OUTPUT);
  digitalWrite(compressor, LOW);
  digitalWrite(drain, LOW);
  digitalWrite(airSupply1, LOW);
  digitalWrite(airSupply2, LOW);

  //configure static ip
  if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
    Serial.println("STA Failed to configure");
  }
  // Connect to WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }


  Serial.println("");
  Serial.println("WiFi connected");
  // Start the server
  server.begin();
  Serial.println("Server started");
  // Print the IP address
  Serial.print("Use this URL to connect: ");
  Serial.print("http://");
  Serial.print(WiFi.localIP());
  Serial.println("/");
}


void loop() {
  WiFiClient client = server.available(); //listen for clients

  if (client) {                           //If a client connects,
    Serial.println("New Client.");        //print message to serial port
    String currentLine = "";              //create string to hold date from client
    currentTime = millis();
    previousTime = currentTime;
    while (client.connected() && currentTime - previousTime <= timeoutTime) { //loop while client is connected
      currentTime = millis();
      if (client.available()) {           //if there is a byte to read from client,
        char c = client.read();           //read the byte, then
        Serial.write(c);                  //print in serial monitor
        header += c;
        if (c == '\n') {                  //if the byte is a newline character
          //if the current line is blank, you get two newline characters in a row.
          //that is the end of the client HTTP request, so send the response:
          if (currentLine.length() == 0) {
            //HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            //and a content-type so the client knows what is comming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();

            //turn the GPIOs on and off
            if (header.indexOf("GET /16/on") >= 0) {
              Serial.println("GPIO 16 on");
              compressorState = "on";
              digitalWrite(compressor, HIGH);
            } else if (header.indexOf("GET /16/off") >= 0) {
              Serial.println("GPIO 16 off");
              compressorState = "off";
              digitalWrite(compressor, LOW);
            } else if (header.indexOf("GET /5/on") >= 0) {
              Serial.println("GPIO 05 on for 5 seconds");
              drainState = "open";
              drainTimeState = HIGH;
              digitalWrite(drain, HIGH);
              drainTime = millis();
              while (drainTimeState == HIGH) {
                Serial.println(millis() - drainTime);
                if (millis() - drainTime > 5000)
                {
                  digitalWrite(drain, LOW);
                  Serial.println("GPIO 05 off");
                  drainState = "closed";
                  drainTimeState = LOW;
                  break;
                }
              }
            } else if (header.indexOf("GET /5/off") >= 0) {
              Serial.println("GPIO 05 off");
              drainState = "closed";
              digitalWrite(drain, LOW);
            } else if (header.indexOf("GET /4/on") >= 0) {
              Serial.println("GPIO 4 on");
              airSupply1State = "on";
              digitalWrite(airSupply1, HIGH);
            } else if (header.indexOf("GET /4/off") >= 0) {
              Serial.println("GPIO 4 off");
              airSupply1State = "off";
              digitalWrite(airSupply1, LOW);
            } else if (header.indexOf("GET /0/on") >= 0) {
              Serial.println("GPIO 0 on");
              airSupply2State = "on";
              digitalWrite(airSupply2, HIGH);
            } else if (header.indexOf("GET /0/off") >= 0) {
              Serial.println("GPIO 0 off");
              airSupply2State = "off";
              digitalWrite(airSupply2, LOW);
            }

            // Display the HTML web page
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            // CSS to style the on/off buttons
            // Feel free to change the background-color and font-size attributes to fit your preferences
            // CSS to style the on/off buttons
            // Feel free to change the background-color and font-size attributes to fit your preferences
            client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
            client.println(".button { background-color: #195B6A; border: none; color: white; padding: 16px 40px;");
            client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
            client.println(".button2 {background-color: #77878A;}</style></head>");

            // Web Page Heading
            client.println("<body><h1>ESP8266 Web Server</h1>");

            // Display current state, and ON/OFF buttons for GPIO 16
            client.println("<p>Compressor Status " + compressorState + "</p>");
            // If the compressorState is off, it displays the ON button
            if (compressorState == "off") {
              client.println("<p><a href=\"/16/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/16/off\"><button class=\"button button2\">OFF</button></a></p>");
            }

            // Display current state, and open/close buttons for GPIO 5
            client.println("<p>Drain Valve Status " + drainState + "</p>");
            // If the drain is closed, it displays the OPEN button
            if (drainState == "closed") {
              client.println("<p><a href=\"/5/on\"><button class=\"button\">OPEN</button></a></p>");
            } else {
              client.println("<p><a href=\"/5/off\"><button class=\"button button2\">CLOSE</button></a></p>");
            }
            // Display current state, and ON/OFF buttons for GPIO 4
            client.println("<p>Air Supply 1 Status " + airSupply1State + "</p>");
            // If the airSupply1State is off, it displays the ON button
            if (airSupply1State == "off") {
              client.println("<p><a href=\"/4/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/4/off\"><button class=\"button button2\">OFF</button></a></p>");
            }

            // Display current state, and open/close buttons for GPIO 0
            client.println("<p>Air Supply 2 Status " + airSupply2State + "</p>");
            // If airSupply2State is off, it displays the ON button
            if (airSupply2State == "off") {
              client.println("<p><a href=\"/0/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/0/off\"><button class=\"button button2\">OFF</button></a></p>");
            }
            client.println("</body></html>");

            // The HTTP response ends with another blank line
            client.println();
            // Break out of the while loop
            break;
          } else {      //if you got a newline, then clear the current line
            currentLine = "";
          }

        } else if (c != '\r') {     //if you get anything but a carriage return character,
          currentLine += c;         //add it to the end of the currentLine
        }
      }
    }
    //Clear the header variable
    header = "";
    //Close the connection
    client.stop();
    Serial.println("Client disconnected.");
    Serial.println("");

  }

}

Remove the while loop, save the current millis() when your drain was activated and check in every loop() run if the millis() value is more than 5000 bigger than the saved value.

Thank you so much! That worked perfectly. I'll paste the updated code below. It was really a pretty simple fix, but you don't know what you don't know. Thank you!

It presents a new issue though, the button does not update when the valve closes. I think I know how to fix that, so I am going to take a stab at it now.

#include <ESP8266WiFi.h>
#include "secret.h"


char ssid[] = SECRET_SSID;
char password[] = SECRET_PASS;

// Set your Static IP address
IPAddress local_IP(192, 168, 1, 123);
// Set your Gateway IP address
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(8, 8, 8, 8);   //optional
IPAddress secondaryDNS(8, 8, 4, 4); //optional
WiFiServer server(80);

//Variable to store HTTP request
String header;

//Auxilliary variable so store the current output state
String compressorState = "off";
String drainState = "closed";
String airSupply1State = "off";
String airSupply2State = "off";

// Assign output variables to GPIO pins
const int compressor = 16; // GPIO16
const int drain = 5; //GPIO05
const int airSupply1 = 4; //GPIO4
const int airSupply2 = 0; //GPIO0

//Current Time
unsigned long currentTime = millis();

//Previous time
unsigned long previousTime = 0;

//Define timeout time in milliseconds
const long timeoutTime = 2000;

//drain timer
static unsigned long drainTime = 0;
static unsigned long drainTimeState = LOW;

void setup() {
  Serial.begin(115200);
  delay(10);
  pinMode(compressor, OUTPUT);
  pinMode(drain, OUTPUT);
  pinMode(airSupply1, OUTPUT);
  pinMode(airSupply2, OUTPUT);
  digitalWrite(compressor, LOW);
  digitalWrite(drain, LOW);
  digitalWrite(airSupply1, LOW);
  digitalWrite(airSupply2, LOW);

  //configure static ip
  if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
    Serial.println("STA Failed to configure");
  }
  // Connect to WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }


  Serial.println("");
  Serial.println("WiFi connected");
  // Start the server
  server.begin();
  Serial.println("Server started");
  // Print the IP address
  Serial.print("Use this URL to connect: ");
  Serial.print("http://");
  Serial.print(WiFi.localIP());
  Serial.println("/");
}


void loop() {
  if (drainTimeState == HIGH)
  {
    Serial.println(millis() - drainTime);
    if (millis() - drainTime > 5000)
    {
      digitalWrite(drain, LOW);
      Serial.println("GPIO 05 off");
      drainState = "closed";
      drainTimeState = LOW;
    }
  }
  WiFiClient client = server.available(); //listen for clients

  if (client) {                           //If a client connects,
    Serial.println("New Client.");        //print message to serial port
    String currentLine = "";              //create string to hold date from client
    currentTime = millis();
    previousTime = currentTime;
    while (client.connected() && currentTime - previousTime <= timeoutTime) { //loop while client is connected
      currentTime = millis();
      if (client.available()) {           //if there is a byte to read from client,
        char c = client.read();           //read the byte, then
        Serial.write(c);                  //print in serial monitor
        header += c;
        if (c == '\n') {                  //if the byte is a newline character
          //if the current line is blank, you get two newline characters in a row.
          //that is the end of the client HTTP request, so send the response:
          if (currentLine.length() == 0) {
            //HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            //and a content-type so the client knows what is comming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();

            //turn the GPIOs on and off
            if (header.indexOf("GET /16/on") >= 0) {
              Serial.println("GPIO 16 on");
              compressorState = "on";
              digitalWrite(compressor, HIGH);
            } else if (header.indexOf("GET /16/off") >= 0) {
              Serial.println("GPIO 16 off");
              compressorState = "off";
              digitalWrite(compressor, LOW);
            } else if (header.indexOf("GET /5/on") >= 0) {
              Serial.println("GPIO 05 on for 5 seconds");
              drainState = "open";
              drainTimeState = HIGH;
              digitalWrite(drain, HIGH);
              drainTime = millis();
            } else if (header.indexOf("GET /5/off") >= 0) {
              Serial.println("GPIO 05 off");
              drainState = "closed";
              digitalWrite(drain, LOW);
            } else if (header.indexOf("GET /4/on") >= 0) {
              Serial.println("GPIO 4 on");
              airSupply1State = "on";
              digitalWrite(airSupply1, HIGH);
            } else if (header.indexOf("GET /4/off") >= 0) {
              Serial.println("GPIO 4 off");
              airSupply1State = "off";
              digitalWrite(airSupply1, LOW);
            } else if (header.indexOf("GET /0/on") >= 0) {
              Serial.println("GPIO 0 on");
              airSupply2State = "on";
              digitalWrite(airSupply2, HIGH);
            } else if (header.indexOf("GET /0/off") >= 0) {
              Serial.println("GPIO 0 off");
              airSupply2State = "off";
              digitalWrite(airSupply2, LOW);
            }

            // Display the HTML web page
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            // CSS to style the on/off buttons
            // Feel free to change the background-color and font-size attributes to fit your preferences
            // CSS to style the on/off buttons
            // Feel free to change the background-color and font-size attributes to fit your preferences
            client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
            client.println(".button { background-color: #195B6A; border: none; color: white; padding: 16px 40px;");
            client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
            client.println(".button2 {background-color: #77878A;}</style></head>");

            // Web Page Heading
            client.println("<body><h1>ESP8266 Web Server</h1>");

            // Display current state, and ON/OFF buttons for GPIO 16
            client.println("<p>Compressor Status " + compressorState + "</p>");
            // If the compressorState is off, it displays the ON button
            if (compressorState == "off") {
              client.println("<p><a href=\"/16/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/16/off\"><button class=\"button button2\">OFF</button></a></p>");
            }

            // Display current state, and open/close buttons for GPIO 5
            client.println("<p>Drain Valve Status " + drainState + "</p>");
            // If the drain is closed, it displays the OPEN button
            if (drainState == "closed") {
              client.println("<p><a href=\"/5/on\"><button class=\"button\">OPEN</button></a></p>");
            } else {
              client.println("<p><a href=\"/5/off\"><button class=\"button button2\">CLOSE</button></a></p>");
            }
            // Display current state, and ON/OFF buttons for GPIO 4
            client.println("<p>Air Supply 1 Status " + airSupply1State + "</p>");
            // If the airSupply1State is off, it displays the ON button
            if (airSupply1State == "off") {
              client.println("<p><a href=\"/4/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/4/off\"><button class=\"button button2\">OFF</button></a></p>");
            }

            // Display current state, and open/close buttons for GPIO 0
            client.println("<p>Air Supply 2 Status " + airSupply2State + "</p>");
            // If airSupply2State is off, it displays the ON button
            if (airSupply2State == "off") {
              client.println("<p><a href=\"/0/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/0/off\"><button class=\"button button2\">OFF</button></a></p>");
            }
            client.println("</body></html>");

            // The HTTP response ends with another blank line
            client.println();
            // Break out of the while loop
            break;
          } else {      //if you got a newline, then clear the current line
            currentLine = "";
          }

        } else if (c != '\r') {     //if you get anything but a carriage return character,
          currentLine += c;         //add it to the end of the currentLine
        }
      }
    }
    //Clear the header variable
    header = "";
    //Close the connection
    client.stop();
    Serial.println("Client disconnected.");
    Serial.println("");

  }

}

Well, my idea didn't work to update the button. I first thought I could add the html to correct the button after the "if" statement that controls the timer. Of course this doesn't work because it's outside of the rest of the html and even if it had, it would have just drawn a new button in the wrong place, so... I added a case to the button state control and had it check the state of drainTimeState and adjust the button, but it only runs each time the client refreshes the page.

I'm thinking now that it may not be possible to refresh only part of the data on the page without resorting to Javascript in the html. If that's the case, I'm way out of my depth and am going to have to study a lot more.

I may just make it so that button says "auto drain" or something and not have it visually change with state. Eventually I'd love to get it dialed in like I'm envisioning, but I'm not really sure how to go after the problem.

Thanks again,
Jason

Post a wiring diagram to update us about what's connected to that valve or a button.

I apologize for the confusion, I was talking about the html based button generated by the we server. There are no physical inputs on this. I'll post a schematic when I'm out to the shop tomorrow.

Thank you,
Jason

Ok, attached below is a rough schematic I drew this AM, hopefully it will clear up the confusion. I'm also attaching three screenshots of the web server output. The first is basically the "ready" state that displays after the board is first booted. The second shows how the HTML responds for any of the non-timed "buttons" when pushed, and the third screenshot shows what happens after the drain valve is actuated. The HTML button switches state properly when "clicked", but of course it never reverts to displaying the correct state on the webpage unless one clicks another button or refreshes the main webpage address.

apparently I'm going to have to attach these one at a time since I am new. I am sorry

Thank you again for taking the time to help.

Jason

This screenshot shows the normal behavior of the HTML buttons and the "status" readings

This one shows the problem with the drain button. In the SS, the valve has been triggered and closed on it's own as intended, but of course the html does not update.

And here is the schematic. Hopefully it comes out legible. I had exported it in PDF, but am not allowed to upload a PDF, so with any luck, this will do.

I got it sorted out and working. There are probably a ton of improvements that can be made, but for now this suits my purpose. I'm attaching the code below in case it can be of any assistance to anyone else.

/*
     Intended to be run on an ESP8266
*/

String header = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n";

String html_1 = R"=====(
<!DOCTYPE html>
<html>
 <head>
 <meta name='viewport' content='width=device-width, initial-scale=1.0'/>
 <meta charset='utf-8'>
 <meta http-equiv='refresh' content='5'>
 <style>
  body {font-size:140%; } 
  #main {display: table; margin: auto;  padding: 0 5px 0 5px;  } 
  h2 {text-align:center; } 
  input[type="button"] { width: 6em; font-size: 120%; }
  .green { background-color: #50FF50;  }
  .red   { background-color: #FF5050;  }  
  table {width: 100%; }
 </style>

<script>
  function switchCompressor() 
  {
     var button_text = document.getElementById("Compressor_button").value;
     if (button_text=="OFF")
     {
       document.getElementById("Compressor_button").value = "ON";
       document.getElementById("Compressor_button").style.background = "#50FF50";
       ajaxLoad('C11'); 
     }
     else
     {
       document.getElementById("Compressor_button").value = "OFF";
       document.getElementById("Compressor_button").style.background = "#FF5050";
       ajaxLoad('C10');
     }
  }

  function switchDrain() 
  {
     var button_text = document.getElementById("Drain_button").value;
     if (button_text=="CLOSED")
     {
       document.getElementById("Drain_button").value = "OPEN";
       document.getElementById("Drain_button").style.background = "#50FF50";
       ajaxLoad('D11'); 
     }
     else
     {
       document.getElementById("Drain_button").value = "CLOSED";
       document.getElementById("Drain_button").style.background = "#FF5050";
       ajaxLoad('D10');
     }
  }

  function switchAir1() 
  {
     var button_text = document.getElementById("Air1_button").value;
     if (button_text=="OFF")
     {
       document.getElementById("Air1_button").value = "ON";
       document.getElementById("Air1_button").style.background = "#50FF50";
       ajaxLoad('A11'); 
     }
     else
     {
       document.getElementById("Air1_button").value = "OFF";
       document.getElementById("Air1_button").style.background = "#FF5050";
       ajaxLoad('A10');
     }
  } 
  function switchAir2() 
  {
     var button_text = document.getElementById("Air2_button").value;
     if (button_text=="OFF")
     {
       document.getElementById("Air2_button").value = "ON";
       document.getElementById("Air2_button").style.background = "#50FF50";
       ajaxLoad('A21'); 
     }
     else
     {
       document.getElementById("Air2_button").value = "OFF";
       document.getElementById("Air2_button").style.background = "#FF5050";
       ajaxLoad('A20');
     }
  }   

  var ajaxRequest = null;
  if (window.XMLHttpRequest)  { ajaxRequest =new XMLHttpRequest(); }
  else                        { ajaxRequest =new ActiveXObject("Microsoft.XMLHTTP"); }


  function ajaxLoad(ajaxURL)
  {
    if(!ajaxRequest){ alert("AJAX is not supported."); return; }
    
    ajaxRequest.open("GET",ajaxURL,true);
    ajaxRequest.onreadystatechange = function()
    {
      if(ajaxRequest.readyState == 4 && ajaxRequest.status==200)
      {
        var ajaxResult = ajaxRequest.responseText;
      }
    }
    ajaxRequest.send();
  }
   
</script>

 <title>Compressor Automation Control</title>
</head>
<body>
 <div id='main'>
  <h2>Compressor Automation Control</h2>
  <table id = "controls">
   <tr>
    <td width="70%">Compressor</td>
)=====";

String html_2 = "    <td> <input type='button' id='Compressor_button' value='OFF' class='red' onclick='switchCompressor()' />  </td>";

String html_3 = R"=====(
   </tr>
   <tr>
    <td width="70%">Drain</td>
)=====";

String html_4 = "    <td> <input type='button' id='Drain_button' value='CLOSED' class='red' onclick='switchDrain()' />  </td>";

String html_5 = R"=====(
   </tr>
   <tr>
    <td width="70%">Air Supply 1</td>
)=====";    

String html_6 = "    <td> <input type='button' id='Air1_button' value='OFF' class='red' onclick='switchAir1()' />  </td>";

String html_7 = R"=====(
   </tr>
   <tr>
    <td width="70%">Air Supply 2</td>
)=====";    

String html_8 = "    <td> <input type='button' id='Air2_button' value='OFF' class='red' onclick='switchAir2()' />  </td>";

String html_9 = R"=====(
    </tr>
    <tr>
    <td width="70%">Current Air Pressure</td>
)=====";

String html_9b = "    <td> <p> %airPressure% PSI</p> </td>";

String html_10 = R"=====(
   </tr>
  </table>
 </div>
</body>
</html>

)=====";


#include "MapFloat.h"
#include <ESP8266WiFi.h>
#include "secret.h"


char ssid[] = SECRET_SSID;
char password[] = SECRET_PASS;

// Set your Static IP address
IPAddress local_IP(192, 168, 1, 123);
// Set your Gateway IP address
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(8, 8, 8, 8);   //optional
IPAddress secondaryDNS(8, 8, 4, 4); //optional network password

WiFiServer server(80);


String request = "";
//Auxilliary variable so store the current output state
String compressorState = "off";
String drainState = "closed";
String airSupply1State = "off";
String airSupply2State = "off";

// Assign output variables to GPIO pins
const int compressor = 16; // GPIO16
const int drain = 5; //GPIO05
const int airSupply1 = 4; //GPIO4
const int airSupply2 = 0; //GPIO0

float airPressure = 0;

//Current Time
unsigned long currentTime = millis();

//Previous time
unsigned long previousTime = 0;

//Define timeout time in milliseconds
const long timeoutTime = 2000;

//drain timer
static unsigned long drainTime = 0;
static unsigned long drainTimeState = LOW;

String tmpString="";

void setup() {
  Serial.begin(115200);
  delay(10);
  pinMode(compressor, OUTPUT);
  pinMode(drain, OUTPUT);
  pinMode(airSupply1, OUTPUT);
  pinMode(airSupply2, OUTPUT);
  digitalWrite(compressor, LOW);
  digitalWrite(drain, LOW);
  digitalWrite(airSupply1, LOW);
  digitalWrite(airSupply2, LOW);

  //configure static ip
  if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
    Serial.println("STA Failed to configure");
  }
  // Connect to WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }


  Serial.println("");
  Serial.println("WiFi connected");
  // Start the server
  server.begin();
  Serial.println("Server started");
  // Print the IP address
  Serial.print("Use this URL to connect: ");
  Serial.print("http://");
  Serial.print(WiFi.localIP());
  Serial.println("/");
}



void loop() 
{
   if (drainTimeState == HIGH)
  {
    Serial.println(millis() - drainTime);
    if (millis() - drainTime > 5000)
    {
      digitalWrite(drain, LOW);
      Serial.println("GPIO 05 off");
      drainState = "closed";
      drainTimeState = LOW;
    }
  }
{
    // Check if a client has connected
    WiFiClient client = server.available();
    if (!client)  {  return;  }
  
    // Read the first line of the request
    request = client.readStringUntil('\r');

    Serial.print("request: "); Serial.println(request);
  

    if       ( request.indexOf("C11") > 0 )  { digitalWrite(compressor, HIGH); compressorState = "On"; }
    else if  ( request.indexOf("C10") > 0 )  { digitalWrite(compressor, LOW); compressorState = "Off"; }
    if       ( request.indexOf("D11") > 0 )  { digitalWrite(drain, HIGH); drainState = "Open"; drainTimeState = HIGH; drainTime=millis();   }
    else if  ( request.indexOf("D10") > 0 )  { digitalWrite(drain, LOW); drainState = "Closed"; drainTimeState = LOW;  }
    if       ( request.indexOf("A11") > 0 )  { digitalWrite(airSupply1, HIGH); airSupply1State = "On"; }
    else if  ( request.indexOf("A10") > 0 )  { digitalWrite(airSupply1, LOW); airSupply1State = "Off";  }
    if       ( request.indexOf("A21") > 0 )  { digitalWrite(airSupply2, HIGH); airSupply2State = "On"; }
    else if  ( request.indexOf("A20") > 0 )  { digitalWrite(airSupply2, LOW); airSupply2State = "Off";  }
    else
    {
       if (digitalRead(compressor)==HIGH) 
       { 
         html_2 = "    <td> <input type='button' id='Compressor_button' value='ON' class='green' onclick='switchCompressor()' />  </td>";
       }
       else
       {
         html_2 = "    <td> <input type='button' id='Compressor_button' value='OFF' class='red' onclick='switchCompressor()' />  </td>";
       }

       
       if (digitalRead(drain)==HIGH) 
       { 
         html_4 = "    <td> <input type='button' id='Drain_button' value='OPEN' class='green' onclick='switchDrain()' />  </td>";
       }
              else
       {
         html_4 = "    <td> <input type='button' id='Drain_button' value='CLOSED' class='red' onclick='switchDrain()' />  </td>";
       }


       if (digitalRead(airSupply1)==HIGH) 
       { 
         html_6 = "    <td> <input type='button' id='Air1_button' value='ON' class='green' onclick='switchAir1()' />  </td>";
       }
       else
       {
         html_6 = "    <td> <input type='button' id='Air1_button' value='OFF' class='red' onclick='switchAir1()' />  </td>";
       }

       if (digitalRead(airSupply2)==HIGH) 
       { 
         html_8 = "    <td> <input type='button' id='Air2_button' value='ON' class='green' onclick='switchAir2()' />  </td>";
       }
       else
       {
         html_8 = "    <td> <input type='button' id='Air2_button' value='OFF' class='red' onclick='switchAir2()' />  </td>";
       }

        client.flush();
        client.print( header );
        client.print( html_1 );    
        client.print( html_2 ); 
        client.print( html_3 ); 
        client.print( html_4 ); 
        client.print( html_5 ); 
        client.print( html_6 ); 
        client.print( html_7 ); 
        client.print( html_8 );
        airPressure = analogRead(A0);
        airPressure = mapFloat(airPressure, 0, 1023, 0, 200);
        tmpString = html_9b;
        tmpString.replace("%airPressure%", String(airPressure));
        client.print( html_9 );
        client.print( tmpString );              
        client.print( html_10 );
        delay(5);
    }

  
  // The client will actually be disconnected when the function returns and 'client' object is detroyed
}
}// void loop()

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.