Client timeout issue.

Me and my friend are building a weather forecaster with feather huzzah esp8266. Our project works, but we have a small timeout issue. Anyone who can help us figure this out?

SMARTTECHproject_19.ino (7.28 KB)

sarahvandenheuvel:
Our project works, but we have a small timeout issue. Anyone who can help us figure this out?

It's going to be difficult unless you describe the problem.

What does your program actually do and what do you want it to do that is different?

...R

Hey Robin! Thanks for helping us out. We want to build this: ESP8266 Weather Forecaster | Random Nerd Tutorials
I'm not sure how to describe our problem, because I never worked with the Feather Huzzah before.
We just know that this timeout appears, and we want to fix it.

We know that he runs the code until the timeout function. We then get our serial.println 'client timeout'. The client.stop then gets activated. It doesn't happen all the time, which is why our weather forecaster works sometimes.

sarahvandenheuvel:
We just know that this timeout appears,

What timeout?

Are you expecting someone here to run your program and study its output? That's very unlikely to happen.

You need to provide the details - such as a sample of the output you get when you run the program.

...R

I honestly don't know why you even comment on our post. Like, this won't help us. We don't know anything about this subject, we're just doing what we can. Have a good day.

try to stop() the connection after reading the response, not 10 minutes later before connect()

sarahvandenheuvel:
we're just doing what we can.

Me too.

...R

Robin2:
Me too.

...R

@Robin2, did you see comment #3?

Juraj:
@Robin2, did you see comment #3?

Yes. I don't understand it - like Reply #2 it is referring to some mysterious timeout.

...R

Robin2:
Yes. I don't understand it - like Reply #2 it is referring to some mysterious timeout.

...R

OP's code

#include <ArduinoJson.h>
 /*
  * Author: Emmanuel Odunlade 
  * Complete Project Details https://randomnerdtutorials.com
  */
  
#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>

// Replace with your SSID and password details
char ssid[] = "";        
char pass[] = "";  

WiFiClient client;

// Open Weather Map API > server name
const char server[] = "api.openweathermap.org";

//  city + BE
//String nameOfCity = "Mechelen,BE"; 
//String apiKey = "b22b9ea4d12a90f2e1d71c55d4d23bf6"; 

String nameOfCity = "Tilburg,NL";
String apiKey = "b22b9ea4d12a90f2e1d71c55d4d23bf6";

String text;

//Json
int jsonend = 0;
boolean startJson = false;
int status = WL_IDLE_STATUS;

int rainLed = 15;//13;  // Indicates rain //blauw-1 (eerste)
int clearLed = 13;//14; // Indicates clear sky or sunny //groen
int snowLed = 12;//11;  // Indicates snow //rood
int thunderstormLed = 14;//4;  // Indicates hail //blauw-1 (laatste)

#define JSON_BUFF_DIMENSION 2500

unsigned long lastConnectionTime = 10 * 60 * 1000;     // last time you connected to the server, in milliseconds
const unsigned long postInterval = 10 * 60 * 1000;  // posting interval of 10 minutes  (10L * 1000L; 10 seconds delay for testing)

// Leds setup
void setup() {
  pinMode(clearLed, OUTPUT);
  pinMode(rainLed, OUTPUT);
  pinMode(snowLed, OUTPUT);
  pinMode(thunderstormLed, OUTPUT);
  Serial.begin(115200);
  
  text.reserve(JSON_BUFF_DIMENSION);

  // Connection > via char ssid and char pass > connecting when correct sidd and pass.
  WiFi.begin(ssid,pass);
  Serial.println("connecting");
  while (WiFi.status() != WL_CONNECTED) { // return the connection status. In WiFi.begin: a connection is established (resulting in WL_CONNECTED)
    delay(500); // wait so as not to send massive amounts of data
    Serial.print(".");
  }
  Serial.println("WiFi Connected");
  printWiFiStatus();
}

/* MILLIS
! the return value for millis() is of type unsigned long, 
logic errors may occur if a programmer tries to do arithmetic with smaller data types such as int. 
Even signed long may encounter errors as its maximum value is half that of its unsigned counterpart.
*/
void loop() { 
  // millis = [time] > Returns the number of milliseconds passed since the Arduino board began running the current program. 
  // this number will overflow (go back to zero), after approximately 50 days.
  // check if 10mins has passed then connect again and pull
  if (millis() - lastConnectionTime > postInterval) {
    // note the time that the connection was made:
    lastConnectionTime = millis();
    makehttpRequest();
  }
}

// print Wifi status
void printWiFiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI(); // gets the signal strength of the connection to the router
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm"); // esp8266/Arduino
}

// to request data from weather site
void makehttpRequest() {
  
 /* 
client is the base class for all Ethernet client based calls. It is not called directly, 
but invoked whenever you use a function that relies on it.
*/
  // disconnect from the server.
  client.stop();

  // if there's a successful connection:
  if (client.connect(server, 80)) {
    /*
    Connects to a specified IP address and port. The return value indicates success or failure. Also supports DNS lookups when using a domain name.
    Syntax client.connect(), client.connect(ip, port), client.connect(URL, port)
    Parameters
      - ip: the IP address that the client will connect to (array of 4 bytes)
      - URL: the domain name the client will connect to (string, ex.:"arduino.cc")
      - port: the port that the client will connect to (int)
    */
    //Serial.println("connecting...");
    // send the HTTP PUT request:
    client.println("GET /data/2.5/forecast?q=" + nameOfCity + "&APPID=" + apiKey + "&mode=json&units=metric&cnt=2 HTTP/1.1");
    client.println("Host: api.openweathermap.org");
    client.println("User-Agent: ArduinoWiFi/1.1");
    client.println("Connection: close");
    client.println();

    Serial.println("HTTP request done...");

    /*
     Unsigned long variables are extended size variables for number storage, and store 32 bits (4 bytes). 
     Unlike standard longs unsigned longs won’t store negative numbers,
     making their range from 0 to 4,294,967,295 (2^32 - 1).
     */
   unsigned long timeout = millis();
    while (client.available() == 0) {
      if (millis() - timeout > 5000) {
       
        Serial.println(">>> Client Timeout !");
        client.stop();
        return;
      }
    }


    Serial.println("Timeout passed...");
        
    char c = 0;
    while (client.available() || client.connected()) {
      if(client.available())
      {
        c = client.read();
        // since json contains equal number of open and close curly brackets, this means we can determine when a json is completely received  by counting
        // the open and close occurences,
        Serial.print(c);
        
        if (c == '{') {
          startJson = true;         // set startJson true to indicate json message has started
          jsonend++;
        }
        if (c == '}') {
          jsonend--;
        }
        if (startJson == true) {
          text+= c;
          delay(0);
        }
        // if jsonend = 0 then we have have received equal number of curly braces 
        if (jsonend == 0 && startJson == true) {
          parseJson(text.c_str());  // parse c string text in parseJson function
          text = "";                // clear text string for the next time
          startJson = false;        // set startJson to false to indicate that a new message has not yet started
        }
      }
    }
     yield();
  }
  else {
    // if no connection was made:
    Serial.println("connection failed");
    return;
  }
}


//to parse json data recieved from OWM
void parseJson(const char * jsonString) {
  //StaticJsonBuffer<4000> jsonBuffer;
  const size_t bufferSize = 2*JSON_ARRAY_SIZE(1) + JSON_ARRAY_SIZE(2) + 4*JSON_OBJECT_SIZE(1) + 3*JSON_OBJECT_SIZE(2) + 3*JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(5) + 2*JSON_OBJECT_SIZE(7) + 2*JSON_OBJECT_SIZE(8) + 720;
  DynamicJsonBuffer jsonBuffer(bufferSize);

  // FIND FIELDS IN JSON TREE
  JsonObject& root = jsonBuffer.parseObject(jsonString);
  if (!root.success()) {
    Serial.println("parseObject() failed");
    return;
  }

  JsonArray& list = root["list"];
  JsonObject& nowT = list[0];
  JsonObject& later = list[1];

  
  String city = root["city"]["name"];
   
  String weatherLater = later["weather"][0]["main"];
  Serial.println();
  Serial.print("Weatherlater = ");
  Serial.println(weatherLater);
  delay(1);

  // Begin JVB edit
  
  if(weatherLater == "Rain" ) {
    digitalWrite(rainLed, HIGH);
    
  } else if(weatherLater == "Clear") {
    digitalWrite(clearLed, HIGH);

  } else if(weatherLater == "Thunderstorm") {
    digitalWrite(thunderstormLed, HIGH);

  } else if(weatherLater == "Snow") {
    digitalWrite(snowLed, HIGH);
  
  } else {
    digitalWrite(rainLed, HIGH);
    digitalWrite(clearLed, HIGH);
    digitalWrite(snowLed, HIGH);
    digitalWrite(thunderstormLed, HIGH);
  }
}
  // End JVB edit

Juraj:
OP's code

I shall bow out of this one as I still have no idea what the OP has a problem with. There seems little point studying code without knowing what the problem is.

...R