Help with arduino weather project

Hey guys, i have tried the following codes below with a few changes to a code i found on this forum, but it doesn’t seem to be working for me. It shows in the serial port that i manage to connect but no information was extracted. I would also like to display it on a LCD 16x2 display. Any help will be great!

// Include description files for other libraries used (if any)
#include <SPI.h>
#include <String.h>
#include <Ethernet.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[] = {0x84, 0x2B, 0x2B, 0xAD, 0xEA, 0xDE };
IPAddress ip ( 172, 16, 156, 39 );
byte server[] = { 140, 90, 113, 200 }; // www.weather.gov
  
// Start ethernet client
EthernetClient client;

void setup()
{
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
 
  // start the Ethernet connection:
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // no point in carrying on, so do nothing forevermore:
    // try to congifure using IP address instead of DHCP:
  Ethernet.begin(mac, ip);
  }
  Serial.println("Starting WebWx");
  Serial.println("connecting...");
  delay(1000);
 
  if (client.connect(server, 80)) {
    Serial.println("connected");
    client.println("GET /xml/current_obs/KRDU.xml HTTP/1.1");   
    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(60000); // 1 minute
    }
    if (client.connect(server, 80)) {
      //Serial.println("Reconnected");
      client.println("GET /xml/current_obs/KRDU.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;
   }
} 
// 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;
   }
}

It would help considerably if you followed the advice in http://forum.arduino.cc/index.php?topic=97455.0, put the code in code tags, eliminated superfluous blank lines and used the Auto Format tool in the IDE.

Hi sorry, forgot to clear the space in between, still a newcomer when it comes to programming thus my code is around the place. As i do not know where the problem is coming from i posted my entire code.

Posting your whole code is good. Using code tags is even better.

Does you program ever call the serialEvent() function ?

Code tags? err. i don’t think so what does it do?

Code tags? err. i don't think so what does it do?

There is a sticky at the top of the forum. A link to it was provided. It's clear that you still haven't read it. Do so now, before you embarrass yourself further.

PaulS:

Code tags? err. i don't think so what does it do?

There is a sticky at the top of the forum. A link to it was provided. It's clear that you still haven't read it. Do so now, before you embarrass yourself further.

I will put my code into a much better format in future. Thank you

Pardon me, as i thought code tags was used when only if you know your mistake.

No. Cade tags are used whenever posting code. Or, rather, they should be.

The serialEvent() function is usually called at the end of each pass through loop IF there is serial data to be read.

The data coming from the server is NOT coming via the serial port, so what the serialEvent() function does is not related to why your code doesn't work.

I will put my code into a much better format in future.

You can edit your previous post, and post the code correctly.

PaulS:

Pardon me, as i thought code tags was used when only if you know your mistake.

No. Cade tags are used whenever posting code. Or, rather, they should be.

The serialEvent() function is usually called at the end of each pass through loop IF there is serial data to be read.

The data coming from the server is NOT coming via the serial port, so what the serialEvent() function does is not related to why your code doesn't work.

Thanks for clearing that up! So could the problem be with how i get the information from the website?

It shows in the serial port that i manage to connect but no information was extracted

In your code, you have:

  while (client.available()) {
    serialEvent();
  }

The name serialEvent() has specific meaning, and is used to read from the serial port. While your does correctly read from the client, you should NOT be using serialEvent() as the name of the function. Since it reads client data, call it clientEvent().

In the function, you have:

  // Read a char
      char inChar = client.read();
   //Serial.print(".");

First, since you are trying to debug the code, you should not have that statement commented out. Second, since you are trying to debug the code, and the code is based on an expected response from the server, and the code is not working, you ought to consider the possibility that the actual response was not the expected response. Printing . each time a character arrives is silly. Print the character, instead. It takes no longer to print one character (the one of interest) than another (the useless .).

PaulS: In your code, you have:

  while (client.available()) {
    serialEvent();
  }

The name serialEvent() has specific meaning, and is used to read from the serial port. While your does correctly read from the client, you should NOT be using serialEvent() as the name of the function. Since it reads client data, call it clientEvent().

In the function, you have:

  // Read a char
      char inChar = client.read();
   //Serial.print(".");

First, since you are trying to debug the code, you should not have that statement commented out. Second, since you are trying to debug the code, and the code is based on an expected response from the server, and the code is not working, you ought to consider the possibility that the actual response was not the expected response. Printing . each time a character arrives is silly. Print the character, instead. It takes no longer to print one character (the one of interest) than another (the useless .).

Thanks, it has cleared up quite abit for me. I will try it out tomorrow as i am not in the office. Will get back once i read up more / looking at my code more thoroughly.

I have managed to get some sort of response through the serial monitor by adjusting that specific area of code which was told is wrong. But the information i received seems to be abit weird. Could anyone please take a look at which part i did not program the code properly to get the code required. Thanks

// Include description files for other libraries used (if any)
#include <SPI.h>
#include <String.h>
#include <Ethernet.h>
#include <LiquidCrystal.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[] = {0x84, 0x2B, 0x2B, 0xAD, 0xEA, 0xDE };
IPAddress ip ( 172, 16, 156, 39 );
byte server[] = { 140, 90, 113, 200 }; // www.weather.gov
  
// Start ethernet client
EthernetClient client;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); 

void setup()
{
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
 
  // start the Ethernet connection:
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // no point in carrying on, so do nothing forevermore:
    // try to congifure using IP address instead of DHCP:
  Ethernet.begin(mac, ip);
  }
  Serial.println("Starting WebWx");
  Serial.println("connecting...");
  delay(1000);
 
  if (client.connect(server, 80)) {
    Serial.println("connected");
    client.println("GET /xml/current_obs/KRDU.xml HTTP/1.1");   
    client.println();
 
    delay(2000);
  } else {
    Serial.println("connection failed");
  } 

}
void loop() {
  // Read serial data in from web:
 if (client.available()) {
    char c = client.read();
    Serial.print(c);
  }
  
 
  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(60000); // 1 minute
    }
    if (client.connect(server, 80)) {
      //Serial.println("Reconnected");
      client.println("GET /xml/current_obs/KRDU.xml HTTP/1.1");   
      client.println();
      delay(2000);
    } else {
      Serial.println("Reconnect failed");
    }      
  }
}
 
// Process each char from web
void serialEvent() {
 
   // Read a char
      char inChar = client.read();

   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;
   }
} 
// 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;
   }
}

There is nothing wrong with the code that processes the return message. Look what a HTTP 301 return code means. We can't see the whole message since you only posted a picture of half of it.

Basically, what the message is trying to say is that the URL you are trying to access is no longer valid. The complete message should tell you what the new URL should be.

Hey sorry for long reply, was out of town.

I have read up about the HTTP 301. I am not sure if what i understand is correct, but it means that the link have been moved somewhere and in the code it would say where it have been moved? So i just have to edit the link am i right?

This is the full picture.

but it means that the link have been moved somewhere

Yes. In your picture, it tells you where. If you'd posted the data as text, instead of a stupid picture, I'd show you where.

Was worried it would be abit long.

Starting WebWx
connecting…
connected
HTTP/1.1 301 Moved Permanently
Date: Tue, 10 Dec 2013 01:27:14 GMT
Server: Apache
Location: http://www.weather.gov/xml/current_obs/KRDU.xml
Content-Length: 320
Content-Type: text/html; charset=iso-8859-1
Connection: Keep-Alive
Age: 0

301 Moved Permanently

Moved Permanently

The document has moved here.


Apache Server at www.weather.gov Port 80

This:

The document has moved here.

tells you where the URL moved to. You need to change your code to request that URL, instead. The http:// part is not part of the GET request. The www.weather.gov isn’t either. So, your GET request should be “GET xml/current_obs/KRDU.xml” with whatever arguments (the stuff following the ?) are needed to make it get your current weather.

Hmm.. i am kind of confused. In my code i put this

if (client.connect(server, 80)) {
    Serial.println("connected");
    client.println("GET /xml/current_obs/KRDU.xml HTTP/1.1");   
    client.println();

so, it supposed to be correct yea? :| or i have to cancel the / before the xml too?