Created on: 13 February 2013
Part 8 of the Arduino Ethernet Shield Web Server Tutorial
With a slight modification to the HTML and JavaScript code in the Arduino sketch from the previous part of this tutorial, the Arduino web server can be made to automatically update the status of a switch on the web page. The button on the web page used to make the AJAX call from the previous part of this tutorial is no longer needed.
Before continuing with this part of the tutorial, you will need to have completed the previous part of this tutorial and understand it.
This video shows the Arduino web server displaying the switch status automatically using AJAX.
Use the same hardware as the previous part of this tutorial – a push button switch interfaced to pin 3 of the Arduino with Ethernet shield.
Only three modifications need to be made to the previous sketch (eth_websrv_AJAX_switch) to automate the AJAX call that updates the switch status on the web page.
The modified sketch is shown here:
/*-------------------------------------------------------------- Program: eth_websrv_AJAX_switch_auto Description: Arduino web server shows the state of a switch on a web page using AJAX. The state of the switch is updated automatically. Does not use the SD card. Hardware: Arduino Uno and official Arduino Ethernet shield. Should work with other Arduinos and compatible Ethernet shields. Software: Developed using Arduino 1.0.3 software Should be compatible with Arduino 1.0 + References: - WebServer example by David A. Mellis and modified by Tom Igoe - Ethernet library documentation: http://arduino.cc/en/Reference/Ethernet - Learning PHP, MySQL & JavaScript by Robin Nixon, O'Reilly publishers Date: 13 February 2013 Author: W.A. Smith, http://startingelectronics.org --------------------------------------------------------------*/ #include <SPI.h> #include <Ethernet.h> // MAC address from Ethernet shield sticker under board byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; IPAddress ip(10, 0, 0, 20); // IP address, may need to change depending on network EthernetServer server(80); // create a server at port 80 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(3, INPUT); // switch is attached to Arduino pin 3 } 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) { // send a standard http response header client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Connection: keep-alive"); client.println(); // AJAX request for switch state if (HTTP_req.indexOf("ajax_switch") > -1) { // read switch state and send appropriate paragraph text GetSwitchState(client); } else { // HTTP request for web page // send web page - contains JavaScript with AJAX calls client.println("<!DOCTYPE html>"); client.println("<html>"); client.println("<head>"); client.println("<title>Arduino Web Page</title>"); client.println("<script>"); client.println("function GetSwitchState() {"); client.println("nocache = \"&nocache=\"\ + Math.random() * 1000000;"); client.println("var request = new XMLHttpRequest();"); client.println("request.onreadystatechange = function() {"); client.println("if (this.readyState == 4) {"); client.println("if (this.status == 200) {"); client.println("if (this.responseText != null) {"); client.println("document.getElementById(\"switch_txt\")\ .innerHTML = this.responseText;"); client.println("}}}}"); client.println( "request.open(\"GET\", \"ajax_switch\" + nocache, true);"); client.println("request.send(null);"); client.println("setTimeout('GetSwitchState()', 1000);"); client.println("}"); client.println("</script>"); client.println("</head>"); client.println("<body onload=\"GetSwitchState()\">"); client.println("<h1>Arduino AJAX Switch Status</h1>"); client.println( "<p id=\"switch_txt\">Switch state: Not requested...</p>"); client.println("</body>"); client.println("</html>"); } // display received HTTP request on serial port 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) } // send the state of the switch to the web browser void GetSwitchState(EthernetClient cl) { if (digitalRead(3)) { cl.println("Switch state: ON"); } else { cl.println("Switch state: OFF"); } }
The image below shows the modifications that were made to the HTML file that the Arduino sketch sends to the web browser (this file is sent line by line using client.println() in the sketch).
Firstly, the code that creates a button on the web page has been removed as the button is no longer needed. It can be seen commented out in the above image.
The GetSwitchState() function that was previously being called each time the button was pressed is now being called when the page is loaded. This is done by calling the function when the page load event occurs by modifying the <body> tag of the HTML: <body onload="GetSwitchState()">
This is added to the Arduino sketch with the following line of code:
client.println("<body onload=\"GetSwitchState()\">");
The GetSwitchState() function would only be called once when the web page loads, unless we change the code to periodically call this function.
The following line of code is added to the bottom of the GetSwitchState() function to make sure that this function is called every second:
setTimeout('GetSwitchState()', 1000);
What this line of JavaScript code does is call GetSwitchState() every 1000 milliseconds (every second). An AJAX call is therefore made every one second which fetches the status of the switch and updates it on the web page.
This code is added to the web page by adding this line to the Arduino sketch:
client.println("setTimeout('GetSwitchState()', 1000);");