Arduino Ethernet Web Interface

Hi All,
I am new to Arduino (first project), and still getting my head around the coding. I am trying to write a sketch which will enable my Arduino Ethernet to host a web page with buttons. When the buttons are pressed I want the arduino to use this like it would a digital input.
Using examples I have managed to get the Arduino to get an IP address via DHCP, host the page, report back over serial etc.
The page just contains text and the buttons.
In the first instance I would like the button to be able to control the on board LED (pin 9)
Here is my code so far, I imagine it could be neatened up:

/*
  Web LED Control
  Hosts a web page, and writes IP address to serial.
  Connects via DHCP.
 
 */

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

int serial_number = 0;
// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = {  
  0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };

// Initialize the Ethernet client library
// with the IP address and port of the server 
// that you want to connect to (port 80 is default for HTTP):
EthernetServer server(80);

void setup() {
  pinMode(9,OUTPUT);
 // Open serial communications:
  Serial.begin(9600);

  // Start the Ethernet connection:
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // no point in carrying on, so do nothing forevermore:
    for(;;)
      ;
  }
  // print your local IP address:
  Serial.print("My IP address: ");
  for (byte thisByte = 0; thisByte < 3; thisByte++) {
    // print the value of each byte of the IP address:
    Serial.print(Ethernet.localIP()[thisByte], DEC);
    Serial.print(".");
  }
  Serial.println(Ethernet.localIP()[3], DEC);
}

void loop() {
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");  // the connection will be closed after completion of the response
	  // client.println("Refresh: 5");  // refresh the page automatically every 5 sec
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
          client.println("<head>");
          client.println("</head>");
          client.println("<body>");
          client.println("<h1>LED Control</h1>");
          client.println("<p>LED: <button type='button>On</button><button type='button>Off</button>");
          client.println("</body>");
          client.println("</html>");
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        } 
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Serial.println("client disconnected");
  }
}

Can anyone help me to get the Arduino to react to button presses on the web page?

Thanks in advance

Can anyone help me to get the Arduino to react to button presses on the web page?

Sure. But first some questions.

This is an extract of your code:

    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {

// Snipped the part where you send some rubbish

          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        } 
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }

Where do you care what the client’s request was? When you fire up a browser, and point it at the Arduino, the browser generates a GET request. You are getting the GET request, printing it, one character at a time, to the serial port, and then, regardless of what the browser asked for, generating the same (rubbish) response.

You really need to collect the GET request into an array, and understand what the client asked for, and respond appropriately.

Now, as for the comments about a rubbish reply:
client.println("");
client.println("");
client.println("");
client.println("");
client.println("");
client.println(“

LED Control

”);
client.println(“

LED: <button type='button>On<button type='button>Off”);
client.println("");
client.println("");
What is that highlighted bit supposed to do? Without an action field, a button element does nothing.

You should not be using HTML5 features (yet). Generate a form, with submit buttons. The form should have an action field. The action will be executed when a submit button is pressed, causing the browser to generate a new GET request. This new GET request will have additional information appended, including a ? (so you know to do more than serve up the page), the name of the submit button, and any value associated with the submit button. You could name two buttons the same (3, to correspond to pin 3, for instance) and give them different values (0, to mean off; 1, to mean on). Then parsing the “?3=0” part appended to the GET request when the off button was pressed would be easy.

Thanks for your response
Most of the Ethernet stuff came from the Web Server example, and I didn't understand most of it.
Using what you have said, I have now managed to get the buttons on the page and when they are clicked, a new GET request is sent containing the buttons label and value. At the moment, I am still resending the page whenever a GET request is received.
I assume where the page is currently being written, I need to determine what the GET request is for and respond accordingly.
Looking at the serial monitor, all the GET requests are starting "GET /..." with a space after the / being the main page, and "?3=1" or "?3=0" being the respective requests for the two buttons. I think I need to get the string between the / and the next space and use that to determine the appropriate course of action (set the pin high or low), without sending the page to the client again.

Through a lot of trial and error, I have managed to get this to work (see below for code). I am using submit buttons on the web page and reading the GET Requests to determine what was requested and reacting accordingly. However doing this means that each time a button is pressed, the page reloads and I have had to put the html in for each instance of the GET Request.
Is there a way around this? I have seen POST Requests mentioned elsewhere, but I don’t know how to change my code to use them.
Also I imagine there are better ways to do what I have done, so any constructive criticism of the coding would be appreciated.

/*
  Web LED Control
  Hosts a web page, and writes IP address to serial.
  Connects via DHCP. Web page contains buttons which can turn LED on or off.
 
 */

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

// size of buffer used to capture HTTP requests
#define REQ_BUF_SZ   15

String get;
char HTTP_req[REQ_BUF_SZ] = {0}; // buffered HTTP request stored as null terminated string
char req_index = 0;              // index into HTTP_req buffer
// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = {  
  0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };

// Initialize the Ethernet client library
// with the IP address and port of the server 
// that you want to connect to (port 80 is default for HTTP):
EthernetServer server(80);

void setup() {
  pinMode(9,OUTPUT);
 // Open serial communications:
  Serial.begin(9600);

  // Start the Ethernet connection:
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // no point in carrying on, so do nothing forevermore:
    for(;;)
      ;
  }
  // print your local IP address:
  Serial.print("IP address: ");
  for (byte thisByte = 0; thisByte < 3; thisByte++) {
    // print the value of each byte of the IP address:
    Serial.print(Ethernet.localIP()[thisByte], DEC);
    Serial.print(".");
  }
  Serial.println(Ethernet.localIP()[3], DEC);
}

void loop() {
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        if (req_index < (REQ_BUF_SZ - 1)) {
                    HTTP_req[req_index] = c;          // save HTTP request character
                    req_index++;
        }

        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
        Serial.println(HTTP_req);
        String get = HTTP_req;
        if (get.charAt(6) == 'H'){
          // send a standard http response header
            client.println("HTTP/1.1 200 OK");
            client.println("Content-Type: text/html");
            client.println("Connection: close");  // the connection will be closed after completion of the response
            client.println();
            client.println("<!DOCTYPE HTML>");
            client.println("<html>");
            client.println("<head>");
            client.println("</head>");
            client.println("<body>");
            client.println("<h1>LED Control</h1>");
            client.println("<p>LED: <form> <input type='submit' name='9' value='1'></input><input type='submit' name='9' value='0'></input></form></p>");
            client.println("</body>");
            client.println("</html>");
            Serial.println("Page Sent");
        }
       else if (get.charAt(8)=='1'){
          digitalWrite(9,HIGH);
          Serial.println("LED On");
          // send a standard http response header
            client.println("HTTP/1.1 200 OK");
            client.println("Content-Type: text/html");
            client.println("Connection: close");  // the connection will be closed after completion of the response
            client.println();
            client.println("<!DOCTYPE HTML>");
            client.println("<html>");
            client.println("<head>");
            client.println("</head>");
            client.println("<body>");
            client.println("<h1>LED Control</h1>");
            client.println("<p>LED: <form> <input type='submit' name='9' value='1'></input><input type='submit' name='9' value='0'></input></form></p>");
            client.println("</body>");
            client.println("</html>");
        }       
       else if (get.charAt(8)=='0'){
          digitalWrite(9,LOW);
          Serial.println("LED Off");
          // send a standard http response header
            client.println("HTTP/1.1 200 OK");
            client.println("Content-Type: text/html");
            client.println("Connection: close");  // the connection will be closed after completion of the response
            client.println();
            client.println("<!DOCTYPE HTML>");
            client.println("<html>");
            client.println("<head>");
            client.println("</head>");
            client.println("<body>");
            client.println("<h1>LED Control</h1>");
            client.println("<p>LED: <form> <input type='submit' name='9' value='1'></input><input type='submit' name='9' value='0'></input></form></p>");
            client.println("</body>");
            client.println("</html>");
        }  
       else{
         Serial.println("no change");
       }
            req_index = 0;
            get = "";
            break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        } 
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      
       
           
        
      } // end of if client available
    } // end of while client connected
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Serial.println("client disconnected");
  } // end of if client
} // end of loop

Not sure it can really help you, but in An HTTP Server for Arduino Mega with file upload/download and AJAX capabilities - Networking, Protocols, and Devices - Arduino Forum I have posted an HTTP server for MEGA with examples. One of the example pages - "ajax.htm" - is exactly about toggling a LED by buttons, using AJAX and jQuery. In this example you can also toggle the LED on and off automatically with a time delay.
Please indulge me if you find it a bit complex, I understand it is. However, I hope it can help you somehow.
Cheers,
eca

. However doing this means that each time a button is pressed, the page reloads.

You can send the status : 204 back to the browser telling it to not refresh the page and/or embed the return from the server in an imbedded Iframe.

and I have had to put the html in for each instance of the GET Request

I don't understand this situation.

Dave I relate to what you said here:

Using examples I have managed

…here:

Through a lot of trial and error

… and here:

Most of the Ethernet stuff came from the Web Server example, and I didn’t understand most of it.

… and in spite of members’ best efforts to help me get my head round it, I was grateful for a post which pointed me at this tutorial. So I backed off my fumbling and started from scratch with that.

I also, in parallel with that tutorial, have installed Bitnami’s WAMP stack on my laptop and I’m working through some Googled HTML, CSS and Jscript material outside of the Arduino world.