web server page to control LED

First, the LED in this sketch is referred to as pump, I just use and LED on pin 8 for testing the sketch.

Doesn’t toggle correctly. It starts as it should, checks to see if pin 8 is HIGH or LOW and displays the correct radio button to match the state.
Click Pump On, it toggles to on, and the LED lights up. That’s great so far.

Now the problem, back to pump off, and it still thinks its receiving the pump on “get” and displays the Pump On button, but it should now be pump off.

Seems to me like the IndexOf is seeing pump_on, instead of_off… but then if you click pump off again, it does turn off as it should. So that one time around it seems to seeing something else.
any suggestions? thanks

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 0, 14); // IP address, may need to change depending on network
EthernetServer server(80);  // create a server at port 80
//String test;
String http_req;          // stores the HTTP request

void setup() {
    
    Ethernet.begin(mac, ip);  // initialize Ethernet device
    server.begin();           // start to listen for clients
    Serial.begin(9600);       // for diagnostics
    pinMode(8, OUTPUT);       // LED on pin 8
}

void loop() {

EthernetClient client = server.available();  // try to get client

 if (client) {  // got client?
 boolean currentLineIsBlank = true;
 while (client.connected()) {
 if (client.available()) {   // client data available to read
 char c = client.read(); // read 1 byte (character) from client
 http_req += c;  // save the HTTP request 1 char at a time
 // last line of client request is blank and ends with \n
 // respond to client only after last line received
 if (c == '\n' && currentLineIsBlank) {
//Here is the HTML to send
//First send a standard HTTP response header

client.println(F("HTTP/1.1 200 OK"));
client.println(F("Content-Type: text/html"));
client.println(F("Connection: close"));
//client.println(F("Refresh: 5"));  // refresh the page automatically every 5 sec

//  Now send web page
                    client.println(F("<!DOCTYPE html>"));
                    client.println(F("<html>"));
                    client.println(F("<head>"));
                    client.println(F("<title>Control Panel</title>"));
                    client.println(F("<style type=\"text/css\">"));
                    client.println(F("#valveForm {"));
                    client.println(F("margin-top:25px;"));
                    client.println(F("float:left;"));
                    client.println(F("margin-left:150px;"));
                    client.println(F("}"));
                    client.println(F("#pumpForm{"));
                    client.println(F("margin-top:50px;"));
                    client.println(F("float:left;"));
                    client.println(F("margin-left:20px;"));
                    client.println(F("}"));
                    client.println(F("#monitorForm{"));
                    client.println(F("margin-top:25px;"));
                    client.println(F("float:left;"));
                    client.println(F("margin-left:150px;"));
                    client.println(F("}"));
                    client.println(F("</style>"));                  
                    client.println(F("</head>"));
                    client.println(F("<body bgcolor=\"#A1A1A0\">"));
                    client.println(F("<table border=\"2px\" bordercolor=rgb(0,0,0) bgcolor=rgb(255,0,0)>"));
                    client.println(F("<tr>"));
                    client.println(F("<td colspan=\"400\" align=\"center\">"));
                    client.println(F("<h1> Control Panel</h1> </td></tr> </table>"));
                    client.println(F("<div>"));
                    client.println(F("<form id=\"pumpForm\" method=\"get\">"));
                    client.println(F("<table cellspacing=\"4\">"));
                    client.println(F("<tr>"));
                    client.println(F("<th colspan=\"2\" align=\"center\"> Monarch Pump</th> </tr>"));
                   
                    ReceiveResponse(client); 
                    
                  
                    
                    
                    client.println(F("</form>"));
                    client.println(F("</div>"));
// Frm here is just a sample, may be added to a function later - not relevant right now
client.println(F("<div>"));
client.println(F("<form id=\"monitorForm\" method=\"get\">"));
client.println(F("<table>"));
client.println(F("<tr><td> <label for=\"pressure\">Water Pressure:</label></td>"));
client.println(F("<td><input type=\"text\"name=\"pressure\" value=\"55\"style=\"text-align:right;\" maxlength=\"3\" size=\"3\"></td>"));
client.println(F("<td> <font size=\"2\" color=\"blue\"face=\"verdana\">PSI</font></td> </tr>"));
client.println(F("<div>"));
client.println(F("<tr><td><label for=\"Temperature\">Temperature:  </label>   </td>"));
client.println(F("<td> <input type=\"text\"name=\"Temperature\"value=\"85\"style=\"text-align:right;\" maxlength=\"3\"size=\"3\"></td>"));
client.println(F("<td><font size=\"2\" color=\"red\" face=\"verdana\">Degrees Celsius </font></td>"));
client.println(F("</tr>"));
client.println(F("</table>"));
client.println(F("</div>"));
//        This is the end of stuff for the new function later, not relevant right now         
                    client.println(F("</body>"));
                    client.println(F("</html>"));

Serial.print(http_req);
http_req = "";    // finished with request, empty string
break;
 }
// every line of text received from the client ends with \r\n
                if (c == '\n') {
                    // last character on line of received text
                    // starting new line with next character read
                    currentLineIsBlank = true;
                } 
                else if (c != '\r') {
                    // a text character was received from client
                    currentLineIsBlank = false;
                }
            } // end if (client.available())
        } // end while (client.connected())
        delay(1);      // give the web browser time to receive the data
        client.stop(); // close the connection
    } // end if (client)
}
                    


void PumpOnorOff(EthernetClient cl)
{
if (digitalRead(8)==HIGH){
  cl.println(F("<tr>"));
  cl.println(F("<td>"));
  cl.println(F("Pump ON"));
  cl.println(F("</td>"));
  cl.println(F("<td><input type=\"radio\"name=\"pump_state\"value=\"pump_on\"checked=\"checked\"></td>"));
  cl.println(F("<tr><td>Pump OFF</td>"));
  cl.println(F("<td><input type=\"radio\"name=\"pump_state\"value=\"pump_off\"onclick=\"submit();\"></td>"));

}


 else if (digitalRead(8)==LOW){
  cl.println(F("<tr>"));
  cl.println(F("<td>"));
  cl.println(F("Pump ON"));
  cl.println(F("</td>"));
  cl.println(F("<td><input type=\"radio\"name=\"pump_state\"value=\"pump_on\"onclick=\"submit();\"></td>"));
  cl.println(F("<tr><td>Pump OFF</td>"));
  cl.println(F("<td><input type=\"radio\"name=\"pump_state\"value=\"pump_off\"checked=\"checked\"></td>"));

}

}



void ReceiveResponse(EthernetClient cll){
  
  if (http_req.indexOf("pump_state=pump_on")>-1){
  
  digitalWrite(8,HIGH); 
  delay(5000);
  PumpOnorOff(cll);
} 
 
 else if (http_req.indexOf("pump_state=pump_off")>-1){

  digitalWrite(8,LOW); 
  
PumpOnorOff(cll);
 } 

else {
 PumpOnorOff(cll);
 }
}

Why does all your code start in column one?

Why can't you indent your code properly, so it is readable? Tools + Auto Format can.

You set the state of pin 8. Why can't you remember that? There is no reason to read the state of an OUTPUT pin that can ONLY change when you tell it to.

if (digitalRead(8)==HIGH){
 else if (digitalRead(8)==LOW){

Are you planning to add code later to handle the other possible return values? What other possible return values are there?

Since there are only two, if the pin isn't HIGH, there is not a snowball's chance in hell that it is not LOW. When you KNOW that there is no possibility that the comparison will not be true, there is no point in making the comparison.

Look at the first 4 lines in the if block and the else block. How are they different? Why do you need to repeat identical code.

Why is there a delay in the middle of generating the new page?

Why does the text near the radio buttons say PUMP OFF regardless of the state of the pin that the "pump" is attached to?

It’s all still a learning curve for me. That’s why it may not be the way others would do things. I’m learning it bit by bit.

PaulS:
Why
does
all
your
code
start
in
column
one?

Because I didn’t know.

PaulS:
You set the state of pin 8. Why can’t you remember that? There is no reason to read the state of an OUTPUT pin that can ONLY change when you tell it to.

if (digitalRead(8)==HIGH){
 else if (digitalRead(8)==LOW){

Because the first time you call the web page, the state of the pin may be HIGH or LOW from a previous
session from another browser somewhere else. The Pin may have been left on or off, on purpose. So that’s why.

Are you planning to add code later to handle the other possible return values? What other possible return values are there?

Since there are only two, if the pin isn’t HIGH, there is not a snowball’s chance in hell that it is not LOW. When you KNOW that there is no possibility that the comparison will not be true, there is no point in making the comparison.

Just the two, plus the initial request, which checks to see if Pin was left on or off from previous user.

Look at the first 4 lines in the if block and the else block. How are they different? Why do you need to repeat identical code.

I was playing around with a few things when trouble shooting and forgot to remove that back to the main code

Why is there a delay in the middle of generating the new page?

Was using it in some troubleshoot, it’s gone now

Why does the text near the radio buttons say PUMP OFF regardless of the state of the pin that the “pump” is attached to?

If you called this page, you would see that the text PUMP OFF and PUMP ON near the radio buttons are constant labels beside each button. So whether the state is high or low, both buttons have their label.

The Page runs like this on my browser. When page initally requested:

  1. If the pin 8 is off, Radio Button “Pump off” is selected and Radio Button “Pump on” is ready to submit

  2. Click Pump On Radio Button to turn on pump, it turns on pump and returns the proper selected Radio button to the webpage

  3. Click Pump Off, but instead of turning off, pump stays on and the “pump on” radio button is sent as selected again, but it should be the pump off radio button sent as selected.

Here is a cleaned up version of what I got for code.

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 0, 14); // IP address, may need to change depending on network
EthernetServer server(80);  // create a server at port 80
//String test;
String http_req;          // stores the HTTP request

void setup() {

  Ethernet.begin(mac, ip);  // initialize Ethernet device
  server.begin();           // start to listen for clients
  Serial.begin(9600);       // for diagnostics
  pinMode(8, OUTPUT);       // LED on pin 8
}

void loop() {

  EthernetClient client = server.available();  // try to get client

  if (client) {  // got client?
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {   // client data available to read
        char c = client.read(); // read 1 byte (character) from client
        http_req += c;  // save the HTTP request 1 char at a time
        // last line of client request is blank and ends with \n
        // respond to client only after last line received
        if (c == '\n' && currentLineIsBlank) {
          //Here is the HTML to send
          //First send a standard HTTP response header

          client.println(F("HTTP/1.1 200 OK"));
          client.println(F("Content-Type: text/html"));
          client.println(F("Connection: close"));
          //client.println(F("Refresh: 5"));  // refresh the page automatically every 5 sec

          //  Now send web page
          client.println(F("<!DOCTYPE html>"));
          client.println(F("<html>"));
          client.println(F("<head>"));
          client.println(F("<title>Control Panel</title>"));
          client.println(F("<style type=\"text/css\">"));
          client.println(F("#valveForm {"));
          client.println(F("margin-top:25px;"));
          client.println(F("float:left;"));
          client.println(F("margin-left:150px;"));
          client.println(F("}"));
          client.println(F("#pumpForm{"));
          client.println(F("margin-top:50px;"));
          client.println(F("float:left;"));
          client.println(F("margin-left:20px;"));
          client.println(F("}"));
          client.println(F("#monitorForm{"));
          client.println(F("margin-top:25px;"));
          client.println(F("float:left;"));
          client.println(F("margin-left:150px;"));
          client.println(F("}"));
          client.println(F("</style>"));
          client.println(F("</head>"));
          client.println(F("<body bgcolor=\"#A1A1A0\">"));
          client.println(F("<table border=\"2px\" bordercolor=rgb(0,0,0) bgcolor=rgb(255,0,0)>"));
          client.println(F("<tr>"));
          client.println(F("<td colspan=\"400\" align=\"center\">"));
          client.println(F("<h1>Control Panel</h1> </td></tr> </table>"));
          client.println(F("<div>"));
          client.println(F("<form id=\"pumpForm\" method=\"get\">"));
          client.println(F("<table cellspacing=\"4\">"));
          client.println(F("<tr>"));
          client.println(F("<th colspan=\"2\" align=\"center\"> Monarch Pump</th> </tr>"));
          client.println(F("<tr>"));
          client.println(F("<td>"));
          client.println(F("Pump ON"));
          client.println(F("</td>"));
          ReceiveResponse(client);    //Which radio button will be preselected, and which will be ready to submit
          client.println(F("</body>"));
          client.println(F("</html>"));

          Serial.print(http_req);
          http_req = "";    // finished with request, empty string
          break;
        }
        // every line of text received from the client ends with \r\n
        if (c == '\n') {
          // last character on line of received text
          // starting new line with next character read
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          // a text character was received from client
          currentLineIsBlank = false;
        }
      } // end if (client.available())
    } // end while (client.connected())
    delay(1);      // give the web browser time to receive the data
    client.stop(); // close the connection
  } // end if (client)
}



void PumpOnorOff(EthernetClient cl)
{
  if (digitalRead(8) == HIGH) {
    cl.println(F("<td><input type=\"radio\"name=\"pump_state\"value=\"pump_on\"checked=\"checked\"></td></tr>"));
    cl.println(F("<tr><td>Pump OFF</td>"));
    cl.println(F("<td><input type=\"radio\"name=\"pump_state\"value=\"pump_off\"onclick=\"submit();\"></td></tr>"));
  }

  else if (digitalRead(8) == LOW) {
    cl.println(F("<td><input type=\"radio\"name=\"pump_state\"value=\"pump_on\"onclick=\"submit();\"></td></tr>"));
    cl.println(F("<tr><td>Pump OFF</td>"));
    cl.println(F("<td><input type=\"radio\"name=\"pump_state\"value=\"pump_off\"checked=\"checked\"></td></tr>"));
  }
}



void ReceiveResponse(EthernetClient cll) {

  if (http_req.indexOf("pump_state=pump_on") > -1) {
    digitalWrite(8, HIGH);
    PumpOnorOff(cll);
  }
  else if (http_req.indexOf("pump_state=pump_off") > -1) {
    digitalWrite(8, LOW);
    PumpOnorOff(cll);
  }
  else {
    PumpOnorOff(cll); // If Neither pump_state=pump_on or pump_state=pump=off are received, then it will run this
  }                   // To check to see what the state of the LED is, that may have been left on or off from a
}                     // previous session. Once it determines this, it will then send the proper pre-selected radio button
// and send the opposite radio button ready to submit.

If you called this page, you would see that the text PUMP OFF and PUMP ON near the radio buttons are constant labels beside each button. So whether the state is high or low, both buttons have their label.

I would expect, then, that PumpOnorOff() would output both labels.

Because the first time you call the web page, the state of the pin may be HIGH or LOW from a previous session from another browser somewhere else. The Pin may have been left on or off, on purpose. So that's why.

The pin is either HIGH or LOW, depending on what YOUR code wrote to the pin. It is not necessary to read the pin to know what you wrote to it.

Sharing your (commented) Serial output would be good.

This is a copy of the initial serial monitor when you first call the web page. Sorry, I'm not sure the proper way to paste text that is not code. If I should do another way, please let me know. thx.

GET / HTTP/1.1
Accept: */*
Accept-Language: en-us
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; InfoPath.2)
Accept-Encoding: gzip, deflate
Host: 192.168.0.14
Connection: Keep-Alive

This is serial monitor when I push the "Pump ON" radio button. So far all is good.

GET /?pump_state=pump_on HTTP/1.1
Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Referer: http://192.168.0.14/
Accept-Language: en-us
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; InfoPath.2)
Accept-Encoding: gzip, deflate
Host: 192.168.0.14
Connection: Keep-Alive

Now here is the serial monitor when it doesn't work properly going from PUMP ON to PUMP OFF To my untrained eye it looks right, because the first line contains "pump_state=pump_off" which it should, to then go and send the proper radio buttons....

GET /?pump_state=pump_off HTTP/1.1
Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Referer: http://192.168.0.14/?pump_state=pump_on
Accept-Language: en-us
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; InfoPath.2)
Accept-Encoding: gzip, deflate
Host: 192.168.0.14
Connection: Keep-Alive

And this is the serial monitor the next cycle when the Pump Off radio button actually does work properly.

GET /?pump_state=pump_off HTTP/1.1
Accept: */*
Referer: http://192.168.0.14/?pump_state=pump_off
Accept-Language: en-us
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; InfoPath.2)
Accept-Encoding: gzip, deflate
Host: 192.168.0.14
Connection: Keep-Alive

I did notice that if you punch in the address' manually in the browser like http://192.168.0.14/?pump_state=pump_off

and http://192.168.0.14/?pump_state=pump_on

The pump will turn on and off, and the radio buttons will be properly selected as many hundread times as you want to type those in, but soon as you try to send those requests with the radio buttons, things go bad. :confused:

I’m not sure that I see any harm in the checked radio button being checked again. I’d try making the radio button output differ only in the checked/unchecked attribute. That is, both buttons should have the on_click handler associated with them.

Somehow, your referer is getting out of sync.