vulture2600

Web Server for Thermostat RTC

Feb 13th, 2014
591
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.71 KB | None | 0 0
  1. /*--------------------------------------------------------------
  2. Ajax server sketch that serves web page from SD card and sends serial commands to another Arduino
  3. running a thermostat and recieves variable values to send to web client.
  4.  
  5.   Modified from sketch found at
  6.   http://startingelectronics.com/tutorials/arduino/ethernet-shield-web-server-tutorial/SD-card-AJAX-XML-web-server/
  7.   Original Author:  W.A. Smith, http://startingelectronics.com
  8.   References:   - WebServer example by David A. Mellis and
  9.                   modified by Tom Igoe
  10.                 - SD card examples by David A. Mellis and
  11.                   Tom Igoe
  12.                 - Ethernet library documentation:
  13.                   http://arduino.cc/en/Reference/Ethernet
  14.                 - SD Card library documentation:
  15.                   http://arduino.cc/en/Reference/SD
  16.  
  17. Pin layout:
  18. 0  : Hardware serial RX.
  19. 1  : Hardware serial TX.
  20. 2  :
  21. 3 ~:
  22. 4  : SD CS.
  23. 5 ~:
  24. 6 ~:
  25. 7  :
  26. 8  :
  27. 9 ~:
  28. 10~: Ethernet shield CS.
  29. 11~: Ethernet shield MOSI.
  30. 12 : Ethernet shield MISO.
  31. 13 : Ethernet shield CLK.
  32.  
  33. Revisions:
  34. 1.2: Added code to handle if sensor is unplugged on the web page, 02/18/14.
  35. 1.2: Added support for temps down to -40F. 02/20/14.
  36. --------------------------------------------------------------*/
  37.  
  38. #include <SPI.h>
  39. #include <Ethernet.h>
  40. #include <SD.h>
  41.  
  42. #define REQ_BUF_SZ 60 // size of buffer used to capture HTTP requests.
  43.  
  44. byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
  45. IPAddress ip(192, 168, 1, 179); // IP address, may need to change depending on network.
  46. EthernetServer server(80); // create a server at port 80.
  47. File webFile;
  48. char HTTP_req[REQ_BUF_SZ] = {0}; // buffered HTTP request stored as null terminated string.
  49. char req_index = 0; // index into HTTP_req buffer.
  50.  
  51. //variables to serve:
  52. uint8_t tempHold = 0;
  53. int8_t tempAvg = 0;
  54. uint8_t hour = 0;
  55. uint8_t eveningHour = 0;
  56. uint8_t morningHour = 0;
  57. uint8_t tempReduction = 0;
  58. uint8_t door = 0;
  59. uint8_t heater = 0;
  60. int8_t temp1 = 0;
  61. int8_t temp2 = 0;
  62. int8_t temp3 = 0;
  63. int8_t tempOut = 0;
  64.  
  65. unsigned long timeNow = 0, lastUpdate = 0;
  66. String readString;
  67.  
  68. void setup() {
  69.   pinMode(10, OUTPUT);
  70.   digitalWrite(10, HIGH); // disable Ethernet chip.  
  71.   Serial.begin(19200);
  72.      
  73.   if (!SD.begin(4)) { // initialize SD card.
  74.     return;    // init failed.
  75.   } //end if.
  76.  
  77.   if (!SD.exists("index.htm")) { // check for index.htm file.
  78.     return;  // can't find index file.
  79.   } //end if.
  80.  
  81.   Ethernet.begin(mac, ip);
  82.   server.begin();
  83. } //end setup().
  84.  
  85. void loop() {
  86.   timeNow = millis();
  87.   EthernetClient client = server.available();  // try to get client.
  88.  
  89.   if (timeNow - lastUpdate > 10000) { //keeps data fresh when no client connected.
  90.     Serial.println(F("*"));
  91.     lastUpdate = millis();
  92.   } //end if.
  93.    
  94.   if (client) {  // got client?
  95.     boolean currentLineIsBlank = true;
  96.     while (client.connected()) {
  97.       if (client.available()) {
  98.         char c = client.read(); // read 1 byte (character) from client.
  99.         // limit the size of the stored received HTTP request.
  100.         // buffer first part of HTTP request in HTTP_req array (string),
  101.         // leave last element in array as 0 to null terminate string (REQ_BUF_SZ - 1).
  102.         if (req_index < (REQ_BUF_SZ - 1)) {
  103.           HTTP_req[req_index] = c; // save HTTP request character.
  104.           req_index++;
  105.         } //end if.
  106.        
  107.         // last line of client request is blank and ends with \n
  108.         // respond to client only after last line received:
  109.         if (c == '\n' && currentLineIsBlank) { // send a standard http response header.
  110.           client.println(F("HTTP/1.1 200 OK"));
  111.           // remainder of header follows below, depending on if
  112.           // web page or XML page is requested.
  113.           // Ajax request - send XML file:
  114.           if (StrContains(HTTP_req, "ajax_inputs")) { //send rest of HTTP header.
  115.             Serial.println(F("*")); //request all values from thermostat.
  116.             client.println(F("Content-Type: text/xml"));
  117.             client.println(F("Connection: keep-alive"));
  118.             client.println();
  119.             sendCommands();
  120.             XML_response(client); //send XML file containing input states.
  121.           } //end if.
  122.           else { // web page request.
  123.             // send rest of HTTP header:
  124.             client.println(F("Content-Type: text/html"));
  125.             client.println(F("Connection: keep-alive"));
  126.             client.println();
  127.            
  128.             // send web page:
  129.             webFile = SD.open("index.htm");
  130.             if (webFile) {
  131.               while(webFile.available()) {
  132.                 client.write(webFile.read()); //send web page to client.
  133.               } //end while.
  134.               webFile.close();
  135.             } //end if.
  136.           } //end else.
  137.          
  138.           //Serial.print(HTTP_req); // display received HTTP request on serial port.
  139.          
  140.           // reset buffer index and all buffer elements to 0:
  141.           req_index = 0;
  142.           StrClear(HTTP_req, REQ_BUF_SZ);
  143.           break;
  144.         } //end if.
  145.        
  146.         // every line of text received from the client ends with \r\n.
  147.         if (c == '\n') {
  148.         // last character on line of received text.
  149.         // starting new line with next character read.
  150.           currentLineIsBlank = true;
  151.         }  //end if.
  152.         else if (c != '\r') { // a text character was received from client.
  153.           currentLineIsBlank = false;
  154.         } //end if.
  155.       } // end if client.available().
  156.     } // end while client.connected().
  157.     delay(1);      // give the web browser time to receive the data.
  158.     client.stop(); // close the connection.
  159.   } // end if (client).
  160. } //end loop().
  161.  
  162. // checks if received HTTP request contains certain strings then issues serial commands accordingly.
  163. void sendCommands(void) {
  164.   if (StrContains(HTTP_req, "tempUp")) {
  165.     Serial.println(F("h"));  // increase hold temp.
  166.   } //end if.
  167.   else if (StrContains(HTTP_req, "tempDn")) {
  168.     Serial.println(F("n"));  // decrease hold temp.
  169.   } //end else if
  170.   else if (StrContains(HTTP_req, "nightUp")) {
  171.     Serial.println(F("e"));  // night hour increase.
  172.   } //end else if
  173.   else if (StrContains(HTTP_req, "nightDn")) {
  174.     Serial.println(F("d")); // night hour decrease.
  175.   } //end else if
  176.   else if (StrContains(HTTP_req, "dayUp")) {
  177.     Serial.println(F("m")); // day hour increase.
  178.   } //end else if
  179.   else if (StrContains(HTTP_req, "dayDn")) {
  180.     Serial.println(F("j")); //day hour decrease.
  181.   } //end else if
  182.   else if (StrContains(HTTP_req, "tempRUp")) {
  183.     Serial.println(F("t")); // increase temp reduction.
  184.   } //end else if
  185.   else if (StrContains(HTTP_req, "tempRDn")) {
  186.     Serial.println(F("g")); //decrease temp reduction.
  187.   } //end else if
  188. } //end sendCommands().
  189.  
  190. // send the XML file with current variable values
  191. void XML_response(EthernetClient cl) {
  192.   cl.print(F("<?xml version = \"1.0\" ?>"));
  193.   cl.print(F("<inputs>"));
  194.   cl.print(F("<tempAvg>"));
  195.   cl.print(tempAvg);
  196.   cl.print(F("</tempAvg>"));
  197.   cl.print(F("<tempHold>"));
  198.   cl.print(tempHold);
  199.   cl.print(F("</tempHold>"));
  200.   cl.print(F("<hour>"));
  201.   cl.print(hour);
  202.   cl.print(F("</hour>"));
  203.   cl.print(F("<eveningHour>"));
  204.   cl.print(eveningHour - 12);
  205.   cl.print(F("</eveningHour>"));
  206.   cl.print(F("<morningHour>"));
  207.   cl.print(morningHour);
  208.   cl.print(F("</morningHour>"));
  209.   cl.print(F("<tempReduction>"));
  210.   cl.print(tempReduction);
  211.   cl.print(F("</tempReduction>"));
  212.   cl.print(F("<doorState>"));
  213.   cl.print(door);
  214.   cl.print(F("</doorState>"));
  215.   cl.print(F("<heaterState>"));
  216.   cl.print(heater);
  217.   cl.print(F("</heaterState>"));
  218.   cl.print(F("<sensors>"));
  219.   if (temp1 >= -40) {
  220.     cl.print(temp1);
  221.   } //end if.
  222.   else {
  223.     cl.print(F("--"));
  224.   } //end else.
  225.   cl.print(F("</sensors>"));
  226.   cl.print(F("<sensors>"));
  227.   if (temp2 >= -40) {
  228.     cl.print(temp2);
  229.   } //end if.
  230.   else {
  231.     cl.print(F("--"));
  232.   } //end else.
  233.   cl.print(F("</sensors>"));
  234.   cl.print(F("<sensors>"));
  235.   if (temp3 >= -40) {
  236.     cl.print(temp3);
  237.   } //end if.
  238.   else {
  239.     cl.print(F("--"));
  240.   } //end else.
  241.   cl.print(F("</sensors>"));
  242.   cl.print(F("<sensors>"));
  243.   if (tempOut >= -40) {
  244.     cl.print(tempOut);
  245.   } //end if.
  246.   else {
  247.     cl.print(F("--"));
  248.   } //end else.
  249.   cl.print(F("</sensors>"));
  250.   cl.print(F("</inputs>"));
  251. } //end XML_response().
  252.  
  253. // sets every element of str to 0 (clears array)
  254. void StrClear(char *str, char length) {
  255.   for (uint8_t i = 0; i < length; i++) {
  256.     str[i] = 0;
  257.   } //end for.
  258. } //end StrClear().
  259.  
  260. // searches for the string sfind in the string str
  261. // returns 1 if string found
  262. // returns 0 if string not found
  263. char StrContains(char *str, char *sfind) {
  264.   char found = 0;
  265.   char index = 0;
  266.   char len;
  267.  
  268.   len = strlen(str);
  269.    
  270.   if (strlen(sfind) > len) {
  271.     return 0;
  272.   } //end if.
  273.   while (index < len) {
  274.     if (str[index] == sfind[found]) {
  275.       found++;
  276.       if (strlen(sfind) == found) {
  277.         return 1;
  278.       } //end if.
  279.     } //end if.
  280.     else {
  281.       found = 0;
  282.     } //end else.
  283.     index++;
  284.   } //end while.
  285.   return 0;
  286. } //end StrContains().
  287.  
  288. void serialEvent() { //recieves all values from thermostat and saves to global values.
  289.   while (Serial.available()) {
  290.     char c = Serial.read();
  291.     readString += c;
  292.  
  293.     if (c == '*') { //end of packet.
  294.       uint8_t holdEnd = readString.indexOf('h');
  295.       uint8_t avgEnd = readString.indexOf('a');  
  296.       uint8_t hourEnd = readString.indexOf('j');
  297.       uint8_t eveningEnd = readString.indexOf('e');
  298.       uint8_t morningEnd = readString.indexOf('m');
  299.       uint8_t reductionEnd = readString.indexOf('t');
  300.       uint8_t doorEnd = readString.indexOf('d');
  301.       uint8_t heaterEnd = readString.indexOf('f');
  302.       uint8_t temp1End = readString.indexOf('x');
  303.       uint8_t temp2End = readString.indexOf('y');
  304.       uint8_t temp3End = readString.indexOf('z');
  305.       uint8_t tempOutEnd = readString.indexOf('w');
  306.    
  307.       String hold = readString.substring(0, holdEnd);
  308.       tempHold = hold.toInt();
  309.       String avg = readString.substring(holdEnd + 1, avgEnd);
  310.       tempAvg = avg.toInt();
  311.       String hour1 = readString.substring(avgEnd + 1, hourEnd);
  312.       hour = hour1.toInt();
  313.       String evening = readString.substring(hourEnd + 1, eveningEnd);
  314.       eveningHour = evening.toInt();
  315.       String morning = readString.substring(eveningEnd + 1, morningEnd);
  316.       morningHour = morning.toInt();
  317.       String reduction = readString.substring(morningEnd + 1, reductionEnd);
  318.       tempReduction = reduction.toInt();
  319.       String doorCheck = readString.substring(reductionEnd + 1, doorEnd);
  320.       door = doorCheck.toInt();
  321.       String heaterCheck = readString.substring(doorEnd + 1, heaterEnd);
  322.       heater = heaterCheck.toInt();
  323.       String temp1Check = readString.substring(heaterEnd + 1, temp1End);
  324.       if (temp1Check == "--") {
  325.         temp1 = -41;
  326.       } //end if.
  327.       else {
  328.         temp1 = temp1Check.toInt();
  329.       } //end else.
  330.       String temp2Check = readString.substring(temp1End + 1, temp2End);
  331.       if (temp2Check == "--") {
  332.         temp2 = -41;
  333.       } //end if.
  334.       else {
  335.         temp2 = temp2Check.toInt();
  336.       } //end else.
  337.       String temp3Check = readString.substring(temp2End + 1, temp3End);
  338.       if (temp3Check == "--") {
  339.         temp3 = -41;
  340.       } //end if.
  341.       else {
  342.         temp3 = temp3Check.toInt();
  343.       } //end else.
  344.       String tempOutCheck = readString.substring(temp3End + 1, tempOutEnd);
  345.       if (tempOutCheck == "--") {
  346.         tempOut = -41;
  347.       } //end if.
  348.       else {
  349.         tempOut = tempOutCheck.toInt();
  350.       } //end else.
  351.      
  352.       readString = "";
  353.     } //end if.
  354.   } //end while.
  355. } //end serialEvent().
Advertisement
Add Comment
Please, Sign In to add comment