Arduino as a webserver, pure HTML


So, how can you get a webpage like this showing the values of the analog inputs of your Arduino?

Well, of course you need the Ethernet shield with the SD card socket.

It can be done easily by the use of the "HR" tag of HTML (horizontal rule). You can provide length, width, color and the noshade option and it takes you only a few lines of code.
Look for the value assignment of the color variable to see how the colors are produced.
The sketch uses 28,320 bytes so it would run on an Arduino UNO, but if you want to add any code you better go for the ATmega2560. (On the UNO, you have to use pin 10 instead of pin 53 to access the SD card.)

#define FILENAME "Webserver7"
/* see: 
Arduino Cookbook by Michael Margolis 
15.6 Setting Up an Arduino to Be a Web Server (p. 511)
tested 24.9.14 with SD card: o.k.
Web Server
A simple web server that shows the values of the analog input pins.
*/
#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
char outBuf[128]; // global, written to in eRcv, in this unit only read
byte by[6];
byte mac[4]; 

int port = 80;
EthernetServer server(port);
File fh;
int count = 0;

void setup() {
  Serial.begin(9600);
  Serial.println(FILENAME);

  pinMode(53, OUTPUT); // the Pin on the ATmega2560 / ATmega1280
  digitalWrite(53, HIGH);
  if (SD.begin(4) == 0) { Serial.println("Error-SD"); } 
  String temp; 
  fh = SD.open("config.txt");  
  if (!fh) return;
  temp = getValue(fh,"mac");
  string2bytes(temp);
    
  // set my IP address:
  temp = getValue(fh,"ip");
  string2bytes(temp);
  IPAddress ip(by[0],by[1],by[2],by[3]);
  printIPaddress("IP address: ");
    
  // set the gateway IP address:
  temp = getValue(fh,"gateway");
  string2bytes(temp);
  IPAddress gateway(by[0],by[1],by[2],by[3]);
  printIPaddress("Gateway address: ");
    
  // set the subnet IP address:
  temp = getValue(fh,"subnet");
  string2bytes(temp);
  IPAddress subnet(by[0],by[1],by[2],by[3]);
  printIPaddress("Subnet address: ");

  Ethernet.begin(mac, ip);
  Serial.println(Ethernet.localIP());
  server.begin();
  Serial.println("Server started ");
}

void loop() {
  EthernetClient client = server.available();
  if (client) {
    // an http request ends with a blank line
    boolean current_line_is_blank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.print(c);
        // if we've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so we can send a reply
        if (c == '\n' && current_line_is_blank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();                          // <- this line is essential!
          client.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">");
          client.println("<html>");
          client.println("<head>");
          client.print("<meta http-equiv=\"refresh\" content=\"2; URL=http://");
          client.print(Ethernet.localIP());
          client.println("/\">");
          client.println("</head>");
          client.println("<body bgcolor=#999999>");          
          client.println();
          // output the value of each analog input pin:
          client.println(FILENAME);
          client.println("<p> request no: ");
          client.println(count++);
          client.println("<p>");
          client.println("<table border=1 width=100%>");
          client.print("<colgroup> ");
          client.print("<col width=10> ");
          client.print("<col width=20> ");
          client.println("</colgroup> ");
          for (int i = 0; i < 6; i++) {
            client.print("<tr> <td>");
            client.print(i);
            client.print("</td> <td>");
            int x = analogRead(i);
            client.print(x);
            client.print("</td> <td> <hr color=#");
            long color = 0x1FFF0000 >> (3*i); 
            color = color & 0xffffff;
            if (color < 0x100000) client.print("0");
            if (color < 0x10000) client.print("0");
            client.print(color,HEX);
            client.print(" noshade align=left size=20 width=");
            client.print(100L * x / 1024);
            client.println("%> </td> </tr>");
          }
          client.print("</table>");
          client.println("</body>");
          client.println("</html>");
          break;
        }
        if (c == '\n') {
          // we're starting a new line
          current_line_is_blank = true;
        } else if (c != '\r') {
          // we've gotten a character on the current line
          current_line_is_blank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    client.stop();
  }
}

// get value from the config file
String getValue(File f, String s1) {
  // sequential search for string s1 in file f
  // returns the rest behind "="
  boolean EOL = !f.available();
  boolean found = false;
  String s2;
  f.seek(0);
  while (!found) {
    while (!EOL) {
      char c = f.read();
      if (c != '\n') s2.concat(c); else EOL = true;
    }
    EOL = false;
    if (s2.startsWith(s1)) {
      found = true;
      if (found) {
        int p = s1.length();
        s2 = s2.substring(p+1); // start behind "=" 
        s2.trim(); // cut CR/LF 
        return s2;
      }
    } else s2 = "";
  }
}

// copies bytes from a string to the global array by[]
void string2bytes(String s) { //, byte n) {
  s.toCharArray(outBuf, s.length()+1);
  char *tStr = strtok(outBuf,",");
  // these numbers will be coied into by[]:
  int i = 0;
  while (tStr != NULL) {
    by[i] = atoi(tStr);
    tStr = strtok(NULL,",");
    i++;
  }
}

// dump the data found on the  SD card
void printIPaddress(String name) {
  Serial.print(name);
  for (int i = 0; i < 3; i++) {
    Serial.print(by[i]);
    Serial.print("."); 
  } Serial.println(by[3]);
}

Don't forget to insert an SD card (the smallest one you can get) containing a "config.txt" file with the data of your network, looking something like this:

; data of the Arduino:
mac=144,162,218,0,89,220
ip=192,168,0,220
; data of the LAN:
gateway=192,168,0,1
subnet=255,255,255,0
; end



contact: nji(at)gmx.de