SD Card web page that toggles button image

Hello,
I’ve got a simple project where I’m controlling some I/O pins via a webpage. All that works fine, but I wanted to add button images as indicators. I thought it would be easy enough to do, but I’ve been pulling my hair out over this for the past few hours with no luck. Basically I just want to toggle the image when I click on the button so it goes from a red button to a green button.

Here’s my sketch. I stripped it down a single button to simplify it.

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
#define REQ_BUF_SZ 60

byte mac[] = {0x90,0xA2,0xDA,0x0E,0x99,0x50};
IPAddress ip(192,168,1,100);
EthernetServer server(80); 

File webFile;                    
char HTTP_req[REQ_BUF_SZ] = {0}; 
char req_index = 0; 

int LEDState;
int ledPin = 5; 

void setup()
{
   // disable Ethernet chip
   pinMode(10, OUTPUT);
   digitalWrite(10, HIGH);  
   Serial.begin(9600);       // for debugging
   
   Serial.println("Initializing SD card...");   // initialize SD card
   if (!SD.begin(4)) {
      Serial.println("ERROR - SD card initialization failed!");
      return;
   }
   Serial.println("SUCCESS - SD card initialized.");

   if (!SD.exists("index.htm")) {   // check for index.htm file
      Serial.println("ERROR - Can't find index.htm file!");
      return; 
   }
   Serial.println("SUCCESS - Found index.htm file.");

   pinMode(ledPin, OUTPUT);   // Lights
    
   Ethernet.begin(mac, ip);  // initialize Ethernet device
   server.begin();           // start to listen for clients
}

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
            
            if (req_index < (REQ_BUF_SZ - 1)) {
               HTTP_req[req_index] = c;          // save HTTP request character
               req_index++;
            }
            if (c == '\n' && currentLineIsBlank) {
                              
               // If AJAX Request
               if (StrContains(HTTP_req, "ajax_inputs")) {
                  client.println("HTTP/1.1 200 OK");
                  client.println("Content-Type: text/xml");
                  client.println("Connection: keep-alive");
                  client.println();
                  SetLED();
                  XML_response(client);
               }
               else { 
                  client.println("HTTP/1.1 200 OK");
                  client.println("Content-Type: text/html");
                  client.println("Connection: keep-alive");
                  client.println();
                  webFile = SD.open("index.htm");

                  if (webFile) {
                     while(webFile.available()) {
                        client.write(webFile.read()); // send web page to client
                     }
                     webFile.close();
                  }
               }
               Serial.print(HTTP_req);   // display received HTTP request on serial port
               
               // reset buffer index and all buffer elements to 0
               req_index = 0;
               StrClear(HTTP_req, REQ_BUF_SZ);
               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') {
               currentLineIsBlank = false; // a text character was received from client
            }
         } // 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 SetLED(){
   if (StrContains(HTTP_req, "&LED=1")) {
      LEDState = 1;
      digitalWrite(ledPin, HIGH);
   }
   else if (StrContains(HTTP_req, "&LED=0")) {
      LEDState = 0;
      digitalWrite(ledPin, LOW);
   }
}

//  Send XML file with updated values
void XML_response(EthernetClient cl){
   int analog_in;       // Analog read value
    
   cl.print("<?xml version = \"1.0\" ?>");
   cl.print("<inputs>");
   
   cl.print("<LED>");
   if (LEDState) {
      cl.print("ON");
   }
   else {
      cl.print("OFF");
   }
   cl.println("</LED>");
   
   cl.print("</inputs>");
}

// sets every element of str to 0 (clears array)
void StrClear(char *str, char length){
   for (int i = 0; i < length; i++) {
      str[i] = 0;
   }
}

// searches for the string sfind in the string str
// returns 1 if string found
// returns 0 if string not found
char StrContains(char *str, char *sfind){
   char found = 0;
   char index = 0;
   char len;
   len = strlen(str);
    
   if (strlen(sfind) > len) {
      return 0;
   }
   while (index < len) {
      if (str[index] == sfind[found]) {
         found++;
         if (strlen(sfind) == found) {
            return 1;
         }
      }
      else {
         found = 0;
      }
      index++;
   }
   return 0;
}

And my index.htm

<!DOCTYPE html>

<html>
   <head>
   <title>LED</title>
   <script>
      strLED = "";
      var LED_state = 0;
	
      function GetArduinoIO() {
         nocache = "&nocache=" + Math.random() * 1000000;
         var request = new XMLHttpRequest();
         request.onreadystatechange = function(){
            if (this.readyState == 4)  {
               if (this.status == 200) {
                  if (this.responseXML != null) {
                     if (this.responseXML.getElementsByTagName('LED')[0].childNodes[0].nodeValue == "ON") {
                        document.getElementById("LEDButton").src = "onbutton.jpg";
                        document.getElementById("LEDText").innerHTML = "ON";
                        LED_state = 1;
                     }
                     else {
                        document.getElementById("LEDButton").src = "offbutton.jpg";
                        document.getElementById("LEDText").innerHTML = "OFF";
                        LED_state = 0;
                     }
                  }
               }
            }
         }		
         request.open("GET", "ajax_inputs" + strLED + nocache, true);
         request.send(null);
         setTimeout('GetArduinoIO()', 1000);
         strLED = "";
      }
      function SetLED() {
         if (LED_state == 1) {
            LED_state = 0;
            strLED = "&LED=0";
            // document.getElementById("LEDButton").src = "offbutton.jpg";
            // document.getElementById("LEDText").innerHTML = "OFF";
         }
         else {
            LED_state = 1;
            strLED = "&LED=1";
            // document.getElementById("LEDButton").src = "onbutton.jpg";
            // document.getElementById("LEDText").innerHTML = "ON";
         }
      }
      </script>
      </head>
      <body onload="GetArduinoIO()">
         <input type="image" id="LEDButton" src="offbutton.jpg" width="48" height="48" onclick="SetLED()">

         <span id="LEDText"></span>
      </body>
</html>

I’ve got the index.htm and both images placed in the root of the SD card. Page loads fine, and the ON/OFF text toggles and the LED turns on/off, but just no clue on how to get the image to display. The commented code in the SetLED() function was for testing. It works fine if I just open the file in my browser. I’m sure there’s better ways to mange this, but it’s my first time with a web server and javascript and I guess HTML for that matter, so please be kind :slight_smile: Thanks for any help!

Isn't it an issue of the client browser refreshing the page somehow ?

Well kind of I think. From my understanding the client browser requests the web page. Once the page loads, it sees that it needs an image so sends a request back to the server. If it were a standard image object () then the browser sends a request like “GET /imagename.ext”. Then the server would have some code to handle that. Except this doesn’t seem to be the case for an input object, or at least I can’t see anything different in the GET request.