Webserver javascript read xml on SDcard

I am working on an Arduino-based aquarium controller using a Mega 2560 and ethernet shield using the sd card. Various settings (set temperature, lighting schedules) are accessible through forms on a web page hosted on the ethernet shield. I have decided to store variable values in an xml file on the sd card. Not the simplest solution but I did this for two reasons; 1 - allows for retrieval of variables in case of reset and 2 - allows for display of current variable values on the web page.

On the html page, javascript reads the xml file, then populates the form with the current values. This works perfectly when I run it on my localhost. Once I upload the .htm and .xml files to the sd card, however, it does not work when accessed through the arduino webserver.

I have found a few similar examples out there, but most of these request the xml directly from the arduino, not a file in storage.

Any idea what I am doing wrong? Pertinent code is pasted below.

XML

<?xml version='1.0' ?> 
<settings>
<settemp>27.0</settemp>
<whiONh>10</whiONh>
<whiONm>15</whiONm>
<whiOFFh>12</whiOFFh>
<whiOFFm>15</whiOFFm>
</settings>

HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <meta http-equiv="Content-type" content="text/html;charset=UTF-8">
    <title>Arduino Page</title>
		
   <script type="text/javascript">
		
	function GetSettings() {
			
		if(window.XMLHttpRequest) {
			xmlhttp = new XMLHttpRequest();
		}
		xmlhttp.open("GET","settings.xml",false);
		xmlhttp.send(null);
		xmlDoc = xmlhttp.responseXML;
				
		document.getElementsByName("tset")[0].value = xmlDoc.getElementsByTagName("settemp")[0].childNodes[0].nodeValue;
		document.getElementsByName("lwho")[0].value = xmlDoc.getElementsByTagName("whiONh")[0].childNodes[0].nodeValue;
		document.getElementsByName("lwmo")[0].value = xmlDoc.getElementsByTagName("whiONm")[0].childNodes[0].nodeValue;
		document.getElementsByName("lwhf")[0].value = xmlDoc.getElementsByTagName("whiOFFh")[0].childNodes[0].nodeValue;
		document.getElementsByName("lwmf")[0].value = xmlDoc.getElementsByTagName("whiOFFm")[0].childNodes[0].nodeValue;
				
	}
			
  </script>
		
  </head>
  <body onload="GetSettings()">
	<p>Set Temp
		<form name="temp" method="get" action="" >
			<select name="tset" id="tset" onchange="submit();" >	
				<option value="24.0">24.0</option>
				<option value="24.5">24.5</option>
				<option value="25.0">25.0</option>
				<option value="25.5">25.5</option>
				<option value="26.0">26.0</option>
				<option value="26.5">26.5</option>
				<option value="27.0">27.0</option>
				<option value="27.5">27.5</option>
				<option value="28.0">28.0</option>
				<option value="28.5">28.5</option>
				<option value="29.0">29.0</option>
			</select>
           </form>
           <p>
	White ON
            <form name="whiteON" method="get" action="" >
			<select name="lwho" onchange="submit();" >
				<option value="00">00</option>
				<option value="01">01</option>
				<option value="02">02</option>
				<option value="09">09</option>
				<option value="10">10</option>
				<option value="11">11</option>
				<option value="12">12</option>
				<option value="13">13</option>
				<option value="14">14</option>
				<option value="15">15</option>
				<option value="16">16</option>
				<option value="17">17</option>
				<option value="18">18</option>
				<option value="19">19</option>
				<option value="20">20</option>
				<option value="21">21</option>
				<option value="22">22</option>
				<option value="23">23</option>
			</select>
			:
			<select name="lwmo" onchange="submit();" >
				<option value="00">00</option>
				<option value="15">15</option>
				<option value="30">30</option>
				<option value="45">45</option>
			</select>
           </form>
           <p>
           White OFF
           <form name="whiteOFF" method="get" action="" >
			<select name="lwhf" onchange="submit();" >
				<option value="00">00</option>
				<option value="01">01</option>
				<option value="02">02</option>
				<option value="09">09</option>
				<option value="10">10</option>
				<option value="11">11</option>
				<option value="12">12</option>
				<option value="13">13</option>
				<option value="14">14</option>
				<option value="15">15</option>
				<option value="16">16</option>
				<option value="17">17</option>
				<option value="18">18</option>
				<option value="19">19</option>
				<option value="20">20</option>
				<option value="21">21</option>
				<option value="22">22</option>
				<option value="23">23</option>
			</select>
			:
			<select name="lwmf" onchange="submit();" >
				<option value="00">00</option>
				<option value="15">15</option>
				<option value="30">30</option>
				<option value="45">45</option>
			</select>
           </form>
	</body>
</html>

SKETCH

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

float settemp;

// Time as String for forms and settings
String SwhiONh;
String SwhiONm;
String SwhiOFFh;
String SwhiOFFm;

// ETHERNET
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; // ethernet controller MAC address
byte ip[] = {192,168,0,101}; // arduino IP address
byte serverName[] = {192,168,0,108}; // webserver IP address
byte gateway[] = {192, 168, 0, 1 }; // internet access via router
byte subnet[] = {255, 255, 255, 0 }; //subnet mask
EthernetServer server(80);
EthernetClient client; // initialize the library instance:

File webFile; // webpage file on SD card
String readString;

void setup() {
  
  Serial.begin(9600);
 
  // Initialize and check SD card
  Serial.print("Initializing SD card...");
  pinMode(53, OUTPUT); // hardware SS pin as OUTPUT so it works
  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  // check for index.htm file
  if (!SD.exists("index.htm")) {
    Serial.println("ERROR - Can't find index.htm file!");
    return;  // can't find index file
  }
  Serial.println("SUCCESS - Found index.htm file.");
  
  delay(1000); // give the ethernet module time to boot up
  Ethernet.begin(mac,ip,gateway,gateway,subnet); // start Ethernet
  server.begin();
  Serial.print("My IP address: "); // print the Ethernet board/shield's IP address:
  Serial.println(Ethernet.localIP());
  
} // end setup

void loop() {
  
  EthernetClient client = server.available();
  if (client) {
    //boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();

        //read char by char HTTP request
        if (readString.length() < 100) {

          //store characters to string 
          readString += c; 
          //Serial.print(c);
        } 

        //if HTTP request has ended
        if (c == '\n') {

          //now output HTML data header
          if(readString.indexOf('?') >=0) { //don't send new page
            client.println(F("HTTP/1.1 204 Zoomkat"));
            client.println();
            client.println();  
          }
          
          else if (readString.indexOf('settings') > 0) {
            webFile = SD.open("settings.xml");
            if (webFile) {
              client.println(F("HTTP/1.1 200 OK")); //send new page on browser request
              client.println();
                Serial.println("xml sent");
                Serial.println();
              webFile.close();
            }
          }
          
          else {  
            client.println(F("HTTP/1.1 200 OK")); //send new page on browser request
            client.println(F("Content-Type: text/html"));
            client.println();
            // send web page
            webFile = SD.open("index.htm");        // open web page file
            if (webFile) {
              while(webFile.available()) {
                client.write(webFile.read()); // send web page to client
              }
              webFile.close();
            }
         }
           
          delay(1);
          //stopping client
          client.stop();
          Serial.print("readString = ");
          Serial.print(readString);
          Serial.println();
         
          //clearing string for next read
          readString="";
          
        } // end if c = \n
      } // end if client available
    } // end while client connected
  } // end if (client)
      
} // end loop

I managed to get this working with some changes. I decided to use a .csv file instead of .xml. Although it's less readable, it's a little easier to work with.

During setup, the sketch reads the csv file for the settings. When webserver serves up the page, javascript reads the csv file to get the values to populate the settings form. Once the settings form is submitted through the webserver, the sketch takes the new value and writes a new csv file. Then the csv file is read and the sketch variables are changed.

Through all of this the variables are handled as strings. I haven't included it here, but in the readcsv function I will take the strings and convert to int and floats as necessary. Kind of a roundabout way of doing things but it is working!

I should note the javascript handling of my .csv file is quite simple. This means the .csv file must be the same every time, which shouldn't be a problem since it is generated by the sketch.

sample .csv file contents: settemp,25.5,x

html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">
<html>
	<head>
		<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
		<title>Arduino Page</title>
		
		<script type="text/javascript">
			
			function GetSettings() {
				var csvText = [];
				var csvArr = [];
				var csvFile = new XMLHttpRequest();
				csvFile.open("GET","settings.csv",true);
			
				csvFile.onreadystatechange = function() {
					if(csvFile.readyState == 4) {
						if(csvFile.status == 200) {
							if(csvFile.responseXML != null) {
								csvText = csvFile.responseText;
								csvArr = csvText.split(',');
								document.getElementsByName('tset')[0].value = csvArr[1];			
							}
						}	
					}
				}
				csvFile.send(null);
			}
			
		</script>
		
	</head>
   <body onload="GetSettings()">
		
			<p>Arduino Page</p>
			
			Set Temp
			<form name="temp" method="get" action="" >
				<select name="tset" id="tset" onchange="submit();" >	
					<option value="24.0">24.0</option>
					<option value="24.5">24.5</option>
					<option value="25.0">25.0</option>
					<option value="25.5">25.5</option>
					<option value="26.0">26.0</option>
					<option value="26.5">26.5</option>
					<option value="27.0">27.0</option>
					<option value="27.5">27.5</option>
					<option value="28.0">28.0</option>
					<option value="28.5">28.5</option>
					<option value="29.0">29.0</option>
				</select>
           </form>
           
	</body>
</html>

sketch

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

String tempstring;

// ETHERNET
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; // ethernet controller MAC address
byte ip[] = {192,168,0,101}; // arduino IP address
byte serverName[] = {192,168,0,108}; // webserver IP address
byte gateway[] = {192, 168, 0, 1 }; // internet access via router
byte subnet[] = {255, 255, 255, 0 }; //subnet mask
EthernetServer server(80);

File webFile; // webpage file on SD card
String readString;

void setup() {
  
  Serial.begin(9600);
 
  // Initialize and check SD card
  Serial.print("Initializing SD card...");
  pinMode(53, OUTPUT); // hardware SS pin as OUTPUT so it works
  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  // check for index.htm file
  if (!SD.exists("index.htm")) {
    Serial.println("ERROR - Can't find index.htm file!");
    return;  // can't find index file
  }
  Serial.println("SUCCESS - Found index.htm file.");
  
  delay(1000); // give the ethernet module time to boot up
  Ethernet.begin(mac,ip,gateway,gateway,subnet); // start Ethernet
  server.begin();
  
  // get settings from csv file
  readcsv();
  
  Serial.print("tempstring = ");
  Serial.print(tempstring);
  Serial.println();
    
} // end setup

void loop() {
  
  EthernetClient client = server.available();
  if (client) {
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();

        //read char by char HTTP request
        if (readString.length() < 100) {
          //store characters to string 
          readString += c; 
        } 

        //if HTTP request has ended
        if (c == '\n') {
          
          //now output HTML data header
          if(readString.indexOf('?') >=0) { //don't send new page
            client.println(F("HTTP/1.1 204 Zoomkat"));
            client.println();
            client.println();  
          }

          else if (readString.indexOf('settings') >= 0) {
            webFile = SD.open("settings.csv");
            if (webFile) {
              while(webFile.available()) {
                client.write(webFile.read()); 
              }
              webFile.close();
            }
          }
          
          else {  
            client.println(F("HTTP/1.1 200 OK")); //send new page on browser request
            client.println(F("Content-Type: text/html"));
            client.println();
            // send web page
            webFile = SD.open("index.htm");        // open web page file
            if (webFile) {
              while(webFile.available()) {
                client.write(webFile.read()); // send web page to client
              }
              webFile.close();
              Serial.println("html sent");
              Serial.println();
            }
         }
           
         delay(1);
         //stopping client
         client.stop();
         Serial.print("readString = ");
         Serial.print(readString);
         Serial.println();
         
         if(readString.indexOf('?') >= 0 && readString.indexOf('tset') >= 0) { // getting set temp
            
            tempstring = String(String(readString.charAt(11)) + String(readString.charAt(12)) + String(readString.charAt(13)) + String(readString.charAt(14)));
                        
            Serial.print("settemp = ");
            Serial.print(tempstring); 
            Serial.println();
            
            writecsv(tempstring);
     
          }
         
          //clearing string for next read
          readString="";
          
        } // end if c = \n
      } // end if client available
    } // end while client connected
  } // end if (client)
      
} // end loop

void writecsv(String tempstring) {
  File csvFile;
  SD.remove("settings.csv"); // remove old file
  csvFile = SD.open("settings.csv", FILE_WRITE); // create new file
   
  // if the file opened okay, write to it:
  if (csvFile) {
    Serial.print("Writing to settings.csv...");
    
    csvFile.print("settemp,");
    csvFile.print(tempstring + ",");
    csvFile.print("x");
    csvFile.close();
    Serial.println("done.");
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening settings.csv");
  }
  
  readcsv();
  
}

void readcsv() {
  
  File myFile = SD.open("settings.csv");
  if (myFile) {
    Serial.println("settings.csv:");
     String csvRead;
    // read from the file until there's nothing else in it:
    while (myFile.available()) {
        char ltr = myFile.read();
        csvRead += ltr;
    }
    Serial.println(csvRead);
    Serial.println();
    
    int tstart = csvRead.indexOf("settemp") + 8;
    tempstring = String(String(csvRead.charAt(tstart)) + String(csvRead.charAt(tstart + 1)) + String(csvRead.charAt(tstart + 2)) + String(csvRead.charAt(tstart + 3)));
            
  }
}