Server issues?

I am running a simple code.

When I set the server to www.google.com, it connects to the server just fine.

When I change the server to api.wunderground.com, it won't connect using the client.connect(server,80) line.

char server[] = "www.google.com"; // name address for Google (using DNS)

//char server[] = "api.wunderground.com";

Suggestions?

if (client.connect(server, 80)) {
    Serial.println("connected to server");
    // Make a HTTP request:
    client.println("GET /api/myAPIgoeshere/conditions/q/VA/Haymarket.xml HTTP 1.1");
    client.println("Host: api.wunderground.com");
    delay(100);
    client.println("Connection: close");
    client.println();

Suggestions?

Tell us how you connect to api.wunderground.com using a browser.

If it involves https://, the Arduino can't do https.

I can connect to api.wunderground.com with telnet on port 80, and it responds ok.

What does your connection attempt call return?

You are not checking the DNS resolution with your connect attempt. If using a domain name rather than an IP address, the only success return value is '1'. Any other return value, including negative values indicating a DNS fail, are a fail.

if(client.connect(server,80) == 1) {

It is from the code here. GitHub - robotastic/Weather-Clock: An corrected Sketch for the Weather Clock project from the GE Garages Popup

I think everything is working except for the client.connect. The change to == 1 didn't make a difference

mutiny92:
It is from the code here. GitHub - robotastic/Weather-Clock: An corrected Sketch for the Weather Clock project from the GE Garages Popup

I think everything is working except for the client.connect. The change to == 1 didn't make a difference

Is your Ethernet Shield up and running?
Do you use an Ethernet Shield with a Wiznet W5100 chip?

And please remove that:

delay(100);

It doesn't make any sense to block the api.wunderground.com server during the request, except you want to start a denial-of-service attack against that server.

If the server detects the delay-attack during the request, it may shut-down the connection without sending any response back.

Perhaps you'd better send the FULL SOURCE code of your sketch. Currently I cannot see anything about correctly reading the response or correct client.stop() handling in your sketch.

I appreciate it. I am using the leonardo with the Wifi R3 shield by arduino.

#include <Servo.h>
#include <SPI.h>
#include <WiFi.h>

// you need to user ArduinoIDE 1.02 to load this Sketch unless you have upgraded the firmware on you Wifi Shield

// This needs to be set to False is you are not going to have it connected to your computer with the serial monitor open. With Debug on, the clock will wait for a serial monitor to be connected

const boolean DEBUG = true;

enum conditionType {
  GE = 0,
  CLEAR,
  CLOUDY,
  RAIN,
  THUNDERSTORM,
  SNOW
};

Servo dial;

int conditionsIndex[6] = { 
  1, 1, 9, 12, 11, 20}; 

const char *conditions[][20] = {
  // GE
  { 
    "THINKING"   }
  ,
  // CLEAR
  {
    "Clear"    }
  ,
  // CLOUDY
  {
    "Overcast",
    "Scattered Clouds", 
    "Partly Cloudy",
    "Shallow Fog",
    "Partial Fog",
    "Mostly Cloudy",
    "Fog",
    "Fog Patches",
    "Smoke"    }
  ,
  // RAIN
  {
    "Drizzle",
    "Rain",
    "Hail",
    "Mist",
    "Freezing Drizzle",
    "Patches of Fog",
    "Rain Mist",
    "Rain Showers",
    "Unknown Precipitation",
    "Unknown",
    "Low Drifting Widespread Dust",
    "Low Drifting Sand"    }
  ,
  // THUNDERSTORM
  {
    "Thunderstorm",
    "Thunderstorms and Rain",
    "Thunderstorms and Snow",
    "Thunderstorms and Ice Pellets",
    "Thunderstorms with Hail",
    "Thunderstorms with Small Hail",
    "Blowing Widespread Dust",
    "Blowing Sand",
    "Small Hail",
    "Squalls",
    "Funnel Cloud"    }
  ,
  // SNOW
  {
    "Volcanic Ash",
    "Widespread Dust",
    "Sand",
    "Haze",
    "Spray",
    "Dust Whirls",
    "Sandstorm",
    "Freezing Rain",
    "Freezing Fog",
    "Blowing Snow",    
    "Snow Showers",
    "Snow Blowing Snow Mist",
    "Ice Pellet Showers",
    "Hail Showers",
    "Small Hail Showers",
    "Snow",
    "Snow Grains",
    "Low Drifting Snow",
    "Ice Crystals",
    "Ice Pellets"    }
};

/*
*  FILL IN THESE VARIABLES
*/
char ssid[] = "xxxx";           //  your network SSID (name) 
char pass[] = "xxxx";            //  your network password
String apiState = "VA";                 //  the state where you want to montitor weather (in a two letter format)
String apiCity = "Haymarket";         //  the state where you want to monitor weather (each word should be capitalized, replace space with an underscore i.e. New_York).
String apiKey  = "xxxx";    //  the wunderground api token

int status = WL_IDLE_STATUS;            // the Wifi radio's status
WiFiClient client;

const unsigned long requestInterval = 600000; // Update every 60 minutes

char serverName[] = "api.wunderground.com";  
String GETReqeuest = "GET /api/" + apiKey + "/conditions/q/"+ apiState + "/" + apiCity +".xml HTTP/1.1";
boolean requested;
unsigned long lastAttemptTime = 0;            

String currentLine = "";           
String weatherCondition = "";      
String forecast;

boolean readingWeather = false;      
boolean processingData = true;
boolean clockOriented  = true;
int currentCondition;


void setup() {

  dial.attach(9);
  dial.write(30);  // sets servo to thinking orientation
  delay(4000);
  currentLine.reserve(256);
  weatherCondition.reserve(150);

  if(DEBUG) {
    Serial.begin(9600);

    while (!Serial) {
      ; 
    }
  }

  status = WiFi.begin(ssid, pass);
  if ( status != WL_CONNECTED) { 
    if(DEBUG) Serial.println("Couldn't get a wifi connection");
    // don't do anything else:
    while(true);
  } 
  else {
    if (DEBUG) Serial.println("Connected to wifi");
    if (DEBUG) Serial.println("Starting connection...");
    delay(10000);
    connectToServer();
  }
}



void loop()
{
  checkRequest();
  processWeather();
}


void checkRequest() {
  if (client.available()) {
    char inChar = client.read();
    currentLine += inChar; 
    if (inChar == '\n') {
      currentLine = "";
    } 
    if ( currentLine.endsWith("<weather>")) {
      readingWeather = true; 
      weatherCondition = "";
    }
    if (readingWeather) {
      if (inChar != '<') {
        weatherCondition += inChar;
      } 
      else {
        readingWeather = false;
        weatherCondition = weatherCondition.substring(1, weatherCondition.length());
        forecast = weatherCondition;
        if(DEBUG) Serial.print("SERVER CONDITION: ");
        if(DEBUG) Serial.println(weatherCondition);   
        client.stop(); 
        clockOriented  = false;
        processingData = false;
      }
    }
  }   
  else if (millis() - lastAttemptTime > requestInterval) {
    connectToServer();
  }
}


void connectToServer() {
  if(DEBUG) Serial.println("connecting to server...");
  if (client.connect(serverName, 80)) {
    if(DEBUG) Serial.println("connected to server");
    client.println(GETReqeuest);

    client.println("Host: api.wunderground.com");
    client.println("Connection: close");
    client.println();
    clockOriented = true;
  }
  lastAttemptTime = millis();
}   

void processWeather(){
  if (!processingData && clockOriented == false ){
    calculateCondition();
    clockOriented = true;
  }
}

void calculateCondition(){
  if (forecast.indexOf("Light ") >= 0 ) {
    forecast.replace("Light ", "");
  } 
  else if (forecast.indexOf("Heavy ") >= 0 ) {
    forecast.replace("Heavy ", "");
  }

  if(DEBUG) Serial.print("forecast: ");
  if(DEBUG) Serial.print(forecast);
  if(DEBUG) Serial.println();
  
  for ( int i = 0; i < ( sizeof(conditionsIndex) / sizeof(int) ); i++ ) {
    int idx = conditionsIndex[i];
    for (int j = 0; j < idx; j++ ) {
      if ( forecast.equals(conditions[i][j])) {
        currentCondition = i;
      }
    }
  }

  orientClock();
}

void orientClock(){
  int pos = 25;
  int idx = currentCondition;
  switch(idx){
  case 0:
    if(DEBUG) Serial.println("THINKING");
    pos = 30;
    break;
  case 1:
    if(DEBUG) Serial.println("CLEAR");
    pos = 60;
    break;
  case 2:
    if(DEBUG) Serial.println("CLOUDY");    
    pos = 90;
    break;
  case 3:
    if(DEBUG) Serial.println("RAIN");        
    pos = 120;
    break;
  case 4:
    if(DEBUG) Serial.println("THUNDERSTORM");        
    pos = 150;
    break;
  case 5:
    if(DEBUG) Serial.println("SNOW");        
    pos = 180;
    break;
  default:
    pos = 0;
    break;
  }
  for(int i = 0; i < pos; i ++)  
  {                              
    dial.write(i);              
    delay(15);                  
  } 
  delay(5000);
}

void printWifiData() {
  if(DEBUG) {
    // print your WiFi shield's IP address:
    IPAddress ip = WiFi.localIP();
    IPAddress gateway;
    Serial.print("IP Address: ");
    Serial.println(ip);
    // print the SSID of the network you're attached to:
    Serial.print("SSID: ");
    Serial.println(WiFi.SSID());

   
    gateway = WiFi.gatewayIP();
    Serial.print("GATEWAY: ");
    Serial.println(gateway);
   
    // print the received signal strength:
    long rssi = WiFi.RSSI();
    Serial.print("signal strength (RSSI):");
    Serial.print(rssi);
    Serial.println(" dBm");
    // print your MAC address:
    byte mac[6];  
    WiFi.macAddress(mac);
    Serial.print("MAC address: ");
    Serial.print(mac[5],HEX);
    Serial.print(":");
    Serial.print(mac[4],HEX);
    Serial.print(":");
    Serial.print(mac[3],HEX);
    Serial.print(":");
    Serial.print(mac[2],HEX);
    Serial.print(":");
    Serial.print(mac[1],HEX);
    Serial.print(":");
    Serial.println(mac[0],HEX);
  }
}

How much memory is your conditions 2D array of pointers using? That whole chunk of SRAM is being wasted, as that information is NOT going to change. That array belongs in PROGMEM.

String apiState = "VA";                 //  the state where you want to montitor weather (in a two letter format)
String apiCity = "Haymarket";         //  the state where you want to monitor weather (each word should be capitalized, replace space with an underscore i.e. New_York).
String apiKey  = "xxxx";    //  the wunderground api token

Another useless waste of resources. Wrapping a constant string in a String benefits no one.

String GETReqeuest = "GET /api/" + apiKey + "/conditions/q/"+ apiState + "/" + apiCity +".xml HTTP/1.1";

Again, nothing changes in this variable with the misspelled name. So, it should NOT be a String. sprintf() and a fixed size array, or strcpy() and strcat() will accomplish the same thing and not require unwrapping the string.

  currentLine.reserve(256);
  weatherCondition.reserve(150);

You don't have a clue how little memory you have to work with, do you?

mutiny92:
I appreciate it. I am using the leonardo with the Wifi R3 shield by arduino.

Sorry, I don't know anything about WiFi shields, so I cannot help you much.
I'm always using Ethernet W5100 shields only.

But your programming logic for client.connect()/client.stop() looks weird to me.

Possibly your programming logic is trying to establish connections that never are closed?

How often do you establish connections?
Is this frequency of connecting to the service in compliance with the usage limits of your account?

First I'd check, if the number of connections tried withing one hour is within your usage limit at api.wunderground.com, they might lock you out from the server if you don't use the server accordingly to the usage limits, like "number of requests per hour" they might have. I don't know about that.

Then I'd make sure that any previous client connection has been stopped before starting a new connection. Perhaps like that, inserting 2 extra lines of code before establishing a new connection:

void connectToServer() {
  if(DEBUG) Serial.println("connecting to server...");
  client.stop(); // inserted: close any previously existing connection
  delay(1);  // inserted: wait one millisecond before starting new connection
  if (client.connect(serverName, 80)) {
    if(DEBUG) Serial.println("connected to server");
    client.println(GETReqeuest);

    client.println("Host: api.wunderground.com");
    client.println("Connection: close");
    client.println();
    clockOriented = true;
  }
  lastAttemptTime = millis();
}

PaulS,

Do any of those items impact the ability to connect to the server? I attended a GE Garages workshop where they gave us this code to build a weather display.

I can't take credit for the code or the optimal use of resources. I am simply trying to troubleshoot why I can't seem to connect to the api.wunderground server.

I will certainly research the issues you noted, but right now, I am focusing on troubleshooting the client.connect(serverName,80) issue and determine why it doesn't seem to connect.

mutiny92:
Do any of those items impact the ability to connect to the server?

Running out of SRAM and overwriting things can cause all sorts of unexpected errors in what otherwise appears to be working code.