Web server and getting information from the same arduino?

I was trying to have an arduino uno with an Ethernet shield, get information from the national weather service web site and then post it on a web site from the same arduino.

So…

Get info from web ------ post that info along with other info TO web (ardunio being the web server).

Sorry I’m not very savvy when it comes to the correct terms about web servers, clients, etc…

I can get each of the components to work, meaning I can get the information from the web in one code and in a seperate code post my information. But when I combine the codes, nothing really works.

I don’t know how to combine the codes (or if it is even possible!).

Here are the two codes. I used examples and lightly modified them.

Thanks for any insight or help in advance.

//////////////////////////////////////////////
// Get XML formatted data from the web.
// 1/6/08 Bob S. - Created
//
//  Assumptions: single XML line looks like:
//    <tag>data</tag> or <tag>data
//
// Get current weather observation for Raleigh from weather.gov in XML format
//
//////////////////////////////////////////////

// Include description files for other libraries used (if any)
#include <string.h>
#include <Ethernet.h>
#include <SPI.h>


// Define Constants
// Max string length may have to be adjusted depending on data to be extracted
#define MAX_STRING_LEN  20

// Setup vars
char tagStr[MAX_STRING_LEN] = "";
char dataStr[MAX_STRING_LEN] = "";
char tmpStr[MAX_STRING_LEN] = "";
char endTag[3] = {'<', '/', '\0'};
int len;

// Flags to differentiate XML tags from document elements (ie. data)
boolean tagFlag = false;
boolean dataFlag = false;

// Ethernet vars
byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0xE3, 0xCA };
byte ip[] = { 000, 000, 0, 000 };
byte gateway[] = { 000, 000, 0, 0 };
byte server[] = { 140, 90, 113, 200 }; // www.weather.gov

// Start ethernet client
Client client(server, 80);

void setup()
{
  Serial.begin(9600);
  Serial.println("Starting WebWx");
  Serial.println("connecting...");
  Ethernet.begin(mac, ip);
  delay(1000);

  if (client.connect()) {
    Serial.println("connected");
    client.println("GET /xml/current_obs/KMMK.xml HTTP/1.0");    
    client.println();
    delay(2000);
  } else {
    Serial.println("connection failed");
  }  
}

void loop() {

  // Read serial data in from web:
  while (client.available()) {
    serialEvent();
  }

  if (!client.connected()) {
    //Serial.println();
    //Serial.println("Disconnected");
    client.stop();

    // Time until next update
    //Serial.println("Waiting");
//    for (int t = 1; t <= 15; t++) {
//      delay(10000); // 1 minute
//    }

    if (client.connect()) {
      //Serial.println("Reconnected");
      client.println("GET /xml/current_obs/KMMK.xml HTTP/1.0");    
      client.println();
      delay(2000);
    } else {
      Serial.println("Reconnect failed");
    }      
  }
}

// Process each char from web
void serialEvent() {

   // Read a char
	char inChar = client.read();
   //Serial.print(".");
  
   if (inChar == '<') {
      addChar(inChar, tmpStr);
      tagFlag = true;
      dataFlag = false;

   } else if (inChar == '>') {
      addChar(inChar, tmpStr);

      if (tagFlag) {      
         strncpy(tagStr, tmpStr, strlen(tmpStr)+1);
      }

      // Clear tmp
      clearStr(tmpStr);

      tagFlag = false;
      dataFlag = true;      
      
   } else if (inChar != 10) {
      if (tagFlag) {
         // Add tag char to string
         addChar(inChar, tmpStr);

         // Check for </XML> end tag, ignore it
         if ( tagFlag && strcmp(tmpStr, endTag) == 0 ) {
            clearStr(tmpStr);
            tagFlag = false;
            dataFlag = false;
         }
      }
      
      if (dataFlag) {
         // Add data char to string
         addChar(inChar, dataStr);
      }
   }  
  
   // If a LF, process the line
   if (inChar == 10 ) {

/*
      Serial.print("tagStr: ");
      Serial.println(tagStr);
      Serial.print("dataStr: ");
      Serial.println(dataStr);
*/

      // Find specific tags and print data
      if (matchTag("<temp_f>")) {
	      Serial.print("Temp: ");
         Serial.print(dataStr);
      }
      if (matchTag("<relative_humidity>")) {
	      Serial.print(", Humidity: ");
         Serial.print(dataStr);
      }
      if (matchTag("<pressure_in>")) {
	      Serial.print(", Pressure: ");
         Serial.print(dataStr);
         Serial.println("");
      }

      // Clear all strings
      clearStr(tmpStr);
      clearStr(tagStr);
      clearStr(dataStr);

      // Clear Flags
      tagFlag = false;
      dataFlag = false;
   }
}

/////////////////////
// Other Functions //
/////////////////////

// Function to clear a string
void clearStr (char* str) {
   int len = strlen(str);
   for (int c = 0; c < len; c++) {
      str[c] = 0;
   }
}

//Function to add a char to a string and check its length
void addChar (char ch, char* str) {
   char *tagMsg  = "<TRUNCATED_TAG>";
   char *dataMsg = "-TRUNCATED_DATA-";

   // Check the max size of the string to make sure it doesn't grow too
   // big.  If string is beyond MAX_STRING_LEN assume it is unimportant
   // and replace it with a warning message.
   if (strlen(str) > MAX_STRING_LEN - 2) {
      if (tagFlag) {
         clearStr(tagStr);
         strcpy(tagStr,tagMsg);
      }
      if (dataFlag) {
         clearStr(dataStr);
         strcpy(dataStr,dataMsg);
      }

      // Clear the temp buffer and flags to stop current processing
      clearStr(tmpStr);
      tagFlag = false;
      dataFlag = false;

   } else {
      // Add char to string
      str[strlen(str)] = ch;
   }
}

// Function to check the current tag for a specific string
boolean matchTag (char* searchTag) {
   if ( strcmp(tagStr, searchTag) == 0 ) {
      return true;
   } else {
      return false;
   }
}

web server code:

#include <SPI.h> // needed for Arduino versions later than 0018
#include <Ethernet.h>
#include <TextFinder.h>
#include <avr/pgmspace.h> // for progmem
#define P(name) static const prog_uchar name[] PROGMEM // declare a static string
byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0xE3, 0xCA };
byte ip[] = { 000, 000, 0, 000 };
byte gateway[] = { 000, 000, 0, 0 };
char buffer[8]; // buffer holding the requested page name
Server server(80);
int pin = 9;
int switchPin = 2;

void setup()
{
Serial.begin(9600);
Ethernet.begin(mac, ip);
server.begin();
delay(3000);
Serial.println("Ready");
pinMode(pin, OUTPUT);
pinMode(switchPin, INPUT);
digitalWrite(pin, LOW);
digitalWrite(switchPin, HIGH);
}

void loop(){
Client client = server.available();
if (client) {
TextFinder finder(client );
int type = 0;
while (client.connected()) {
if (client.available()) {
// GET, POST, or HEAD
if(finder.getString("","/", buffer,sizeof(buffer))){
if(strcmp(buffer,"POST ") == 0){
finder.find("\n\r"); // skip to the body
// find string starting with "pin", stop on first blank line
// the POST parameters expected in the form pinDx=Y
// where x is the pin number and Y is 0 for LOW and 1 for HIGH


while(finder.findUntil("pinD", "\n\r")){
pin = finder.getValue(); // the pin number
int val = finder.getValue(); // 0 or 1
digitalWrite(pin, val);
//delay(30000);
//digitalWrite(pin, HIGH);
}
}


sendHeader(client,"Votto Vines Warehouse");
//create HTML button to control pin 9
client.println("<h2>Open Garage Door</h2>");
client.print("<form action='/' method='POST'><p><input type='hidden'name='pinD9'");
client.println(" value='0'><input type='submit' value='Off'/></form>");
//create HTML button to turn on pin 9
client.print("<form action='/' method='POST'><p><input type='hidden'name='pinD9'");
client.print(" value='1'><input type='submit' value='Operate Door'/></form>");

client.print("Door is ");
//client.print(i);
//client.print(" is ");
if(digitalRead(pin) == LOW) //not the right pin!
client.print("OPEN!");
else
client.print("CLOSED");
client.println("
");

client.println("</body></html>");
client.stop();
}
break;
}
}
// give the web browser time to receive the data
delay(1);
client.stop();
}
}

//----------------------------------------------------------------

void sendHeader(Client client, char *title){
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
client.print("<html><head><title>");
client.print(title);
client.println("</title><body>");
}

zoomkat posts some code in this forum quite often that combines a server (sends data) and a client (gets data) in one sketch. Look for it.

I was trying to have an arduino uno with an Ethernet shield, get information from the national weather service web site and then post it on a web site from the same arduino.

It isn’t very clear as to what you are trying to do with the “post it on a web site from the same arduino” part of your project. Do you want the arduino to serve up the page with weather info, or are you wanting to just transfer the info to another web server somewhere else? If it is the latter, it would seem that you need to use the arduino client function to connect to two seperate web servers to transfer the information. Don’t think I’ve seen that exact thing done yet, but I think there has been client code capable of connecting to two seperate web servers as needed.

Thanks for the replies gentlemen. Zoomkat, I would love to see that example Paul is talking about.

What I'm trying to do is have the arduino be a web server when my buddy can open his garage door remotely, which I have a good idea of how to do. I was going to add in a DHT22 sensor for indoor temp and have it displayed on the server also. I thought it would be a cool idea to be able to post the current outdoor weather data on the web server. This is where I don't know to proceed. If I take the two codes and combine them, the web server portion will not work, however, I do see the local weather data on the serial monitor.

Below is some combined client/server test code you can try using a browser and the serial monitor. If you want to incorporate an external weather data soruce, you could embed that page in a page the arduino serves up, which might be more simple.

//zoomkat 7-03-12, combined client and server
//simple button GET with iframe code
//for use with IDE 1.0
//open serial monitor and send an g to test client and
//see what the arduino client/server receives
//web page buttons make pin 5 high/low
//use the ' in html instead of " to prevent having to escape the "
//address will look like http://192.168.1.102:84 when submited
//for use with W5100 based ethernet shields
//note that the below bug fix may be required
// http://code.google.com/p/arduino/issues/detail?id=605

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

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //assign arduino mac address
byte ip[] = { 192, 168, 1, 102 }; // ip in lan assigned to arduino
byte gateway[] = { 192, 168, 1, 1 }; // internet access via router
byte subnet[] = { 255, 255, 255, 0 }; //subnet mask
EthernetServer server(84); //server port arduino server will use
EthernetClient client;
char serverName[] = "web.comporium.net"; // (DNS) zoomkat's test web page server
//byte serverName[] = { 208, 104, 2, 86 }; // (IP) zoomkat web page server IP address

String readString; //used by server to capture GET request 

//////////////////////

void setup(){

  pinMode(5, OUTPUT); //pin 5 selected to control
  Ethernet.begin(mac,ip,gateway,gateway,subnet); 
  server.begin();
  Serial.begin(9600); 
  Serial.println("server/client 1.0 test 7/03/12"); // keep track of what is loaded
  Serial.println("Send an g in serial monitor to test client"); // what to do to test client
}

void loop(){
  // check for serial input
  if (Serial.available() > 0) 
  {
    byte inChar;
    inChar = Serial.read();
    if(inChar == 'g')
    {
      sendGET(); // call client sendGET function
    }
  }  

  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; 
          //Serial.print(c);
        } 

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

          ///////////////
          Serial.println(readString); //print to serial monitor for debuging 

            //now output HTML data header
          if(readString.indexOf('?') >=0) { //don't send new page
            client.println("HTTP/1.1 204 Zoomkat");
            client.println();
            client.println();  
          }
          else {   
            client.println("HTTP/1.1 200 OK"); //send new page on browser request
            client.println("Content-Type: text/html");
            client.println();

            client.println("<HTML>");
            client.println("<HEAD>");
            client.println("<TITLE>Arduino GET test page</TITLE>");
            client.println("</HEAD>");
            client.println("<BODY>");

            client.println("<H1>Zoomkat's simple Arduino 1.0 button</H1>");

            client.println("<a href='/?on' target='inlineframe'>ON</a>"); 
            client.println("<a href='/?off' target='inlineframe'>OFF</a>"); 

            client.println("<IFRAME name=inlineframe style='display:none'>");          
            client.println("</IFRAME>");

            client.println("</BODY>");
            client.println("</HTML>");
          }

          delay(1);
          //stopping client
          client.stop();

          ///////////////////// control arduino pin
          if(readString.indexOf("on") >0)//checks for on
          {
            digitalWrite(5, HIGH);    // set pin 5 high
            Serial.println("Led On");
          }
          if(readString.indexOf("off") >0)//checks for off
          {
            digitalWrite(5, LOW);    // set pin 5 low
            Serial.println("Led Off");
          }
          //clearing string for next read
          readString="";

        }
      }
    }
  }
} 

//////////////////////////
void sendGET() //client function to send and receive GET data from external server.
{
  if (client.connect(serverName, 80)) {
    Serial.println("connected");
    client.println("GET /~shb/arduino.txt HTTP/1.0");
    client.println();
  } 
  else {
    Serial.println("connection failed");
    Serial.println();
  }

  while(client.connected() && !client.available()) delay(1); //waits for data
  while (client.connected() || client.available()) { //connected or data available
    char c = client.read();
    Serial.print(c);
  }

  Serial.println();
  Serial.println("disconnecting.");
  Serial.println("==================");
  Serial.println();
  client.stop();

}

I did search on how to embed a page into the arduino web server but came up short.

I'll try that code when I get a chance. Thank you.

Below is some very simple html frame code I’m tinkering with. You can copy it, paste in notepad, and save on the desktop as frame.htm. Double click on the frame.htm icon and the page should open in your default browser. The “data” link above the frame box loads the meta refresh page (bottom) loaded on my arduino, resulting in updating data in the frame. Clicking the “stop” above loads my client test page. I still need to combine the pages so all can be loaded on the arduino.

<HTML>
<HEAD>
<TITLE>Zoomkat's frame test</TITLE>
</HEAD>
Zoomkat's Arduino frame meta refresh test 7/23/12




Arduino analog input data frame:


|<a href='http://192.168.1.102:84' target='DataBox' title=''Voltage on analog input''>DATA</a>|
<a href='http://web.comporium.net/~shb/arduino.txt' target='DataBox' title=''client test page''>STOP</a>|


<iframe src='http://192.168.1.102:84:84' width='350' height='250' name='DataBox'>
</iframe>


</HTML>
// zoomkat meta refresh server test code
// arduino IDE 1.0
// for W5100 ethernet shield
// the IP address will be dependent on your local network/router
// port 80 is default for HTTP, but can be changed as needed
// use IP address like http://192.168.1.102:84 in your brouser
// or http://zoomkat.no-ip.com:84 with dynamic IP service
// use the \ slash to escape the " in the html
// meta refresh set for 2 seconds

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

int x=0; //set refresh counter to 0
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,1,102); // ip in lan
EthernetServer server(84); //server is using port 84

void setup()
{
  // start the server
  Ethernet.begin(mac, ip);
  server.begin();
}

void loop()
{
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
     while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        // see if HTTP request has ended with blank line
        if (c == '\n') {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
          
          //meta-refresh page every 2 seconds
          x=x+1; //page upload counter
          client.println("<HTML>");
          client.print("<HEAD>");
          client.print("<meta http-equiv=\"refresh\" content=\"2\">");
          client.print("<TITLE />Zoomkat's meta-refresh test</title>");
          client.print("</head>");
          client.println("<BODY>");
          client.print("Zoomkat's meta-refresh test IDE 1.0");
          client.println("
");
                    
          client.print("page refresh number ");
          client.println(x); //current refresh count
          client.println("
");
          client.println("
");
          
          client.print("Zoomkat's arduino analog input values:");
          client.println("
");
          client.println("
");
          
          // output the value of each analog input pin
          for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
            client.print("analog input ");
            client.print(analogChannel);
            client.print(" is ");
            client.print(analogRead(analogChannel));
            client.println("
");
            }
           break;
          client.println("</BODY>");
          client.println("</HTML>");
         }
        }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
  }
}