First, don't yell at me for using String class- I didn't write that part and haven't changed the code to C strings yet.
I have been working with a program to read and parse my local weather using the Open Weather Map API and the ArduinoJson library.
When I put the API call into my browser, this is what is returned; a complete weather report (892 characters):
{"cod":"200","message":0,"cnt":2,"list":[{"dt":1572156000,"main":{"temp":40.68,"temp_min":40.68,"temp_max":43.52,"pressure":1027,"sea_level":1027,"grnd_level":1016,"humidity":76,"temp_kf":-1.59},"weather":[{"id":804,"main":"Clouds","description":"overcast clouds","icon":"04n"}],"clouds":{"all":99},"wind":{"speed":1.72,"deg":138},"sys":{"pod":"n"},"dt_txt":"2019-10-27 06:00:00"},{"dt":1572166800,"main":{"temp":42.46,"temp_min":42.46,"temp_max":44.6,"pressure":1024,"sea_level":1024,"grnd_level":1014,"humidity":72,"temp_kf":-1.19},"weather":[{"id":804,"main":"Clouds","description":"overcast clouds","icon":"04n"}],"clouds":{"all":99},"wind":{"speed":3.87,"deg":98},"sys":{"pod":"n"},"dt_txt":"2019-10-27 09:00:00"}],"city":{"id":4955219,"name":"Westford","coord":{"lat":42.0000,"lon":-71.0000},"country":"US","population":21587,"timezone":-14400,"sunrise":1572174768,"sunset":1572212774}}
But, in my code, makehttpRequest(), client.read() only gets 537 characters:
{"cod":"200","message":0,"cnt":2,"list":[{"dt":1572156000,"main":{"temp":40.71,"temp_min":40.71,"temp_max":43.52,"pressure":1027,"sea_level":1027,"grnd_level":1016,"humidity":76,"temp_kf":-1.57},"weather":[{"id":804,"main":"Clouds","description":"overcast clouds","icon":"04n"}],"clouds":{"all":99},"wind":{"speed":1.72,"deg":138},"sys":{"pod":"n"},"dt_txt":"2019-10-27 06:00:00"},{"dt":1572166800,"main":{"temp":42.49,"temp_min":42.49,"temp_max":44.6,"pressure":1024,"sea_level":1024,"grnd_level":1014,"humidity":72,"temp_kf":-1.18},"w
As you can see from my debug print statements, I get to "Reading json...", but never get to "Parsing json..."
.............
WiFi Connected
SSID: Kaywinnet
IP Address: 192.168.1.37
signal strength (RSSI):-74 dBm
...............
connecting to OWM...
Reading json...
{"cod":"200","message":0,"cnt":2,"list":[{"dt":1572156000,"main":{"temp":40.64,"temp_min":40.64,"temp_max":43.52,"pressure":1027,"sea_level":1027,"grnd_level":1016,"humidity":76,"temp_kf":-1.6},"weather":[{"id":804,"main":"Clouds","description":"overcast clouds","icon":"04n"}],"clouds":{"all":99},"wind":{"speed":1.72,"deg":138},"sys":{"pod":"n"},"dt_txt":"2019-10-27 06:00:00"},{"dt":1572166800,"main":{"temp":42.44,"temp_min":42.44,"temp_max":44.6,"pressure":1024,"sea_level":1024,"grnd_level":1014,"humidity":72,"temp_kf":-1.21},"we
connecting to OWM...
Reading json...
{"cod":"200","message":0,"cnt":2,"list":[{"dt":1572156000,"main":{"temp":40.64,"temp_min":40.64,"temp_max":43.52,"pressure":1027,"sea_level":1027,"grnd_level":1016,"humidity":76,"temp_kf":-1.6},"weather":[{"id":804,"main":"Clouds","description":"overcast clouds","icon":"04n"}],"clouds":{"all":99},"wind":{"speed":1.72,"deg":138},"sys":{"pod":"n"},"dt_txt":"2019-10-27 06:00:00"},{"dt":1572166800,"main":{"temp":42.44,"temp_min":42.44,"temp_max":44.6,"pressure":1024,"sea_level":1024,"grnd_level":1014,"humidity":72,"temp_kf":-1.21},"we
My question: Am I doing something wrong in the client.read() that I can only get 537 characters?
Thanks.
The sketch:
#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
char ssid[] = "Kaywinnet";
char pass[] = "806194XXXX";
WiFiClient client;
const char server[] = "api.openweathermap.org";
String nameOfCity = "Westford,US";
String apiKey = "01dfa35f9f31ede6d6f99dXXXXXXXXXX";
String text;
int jsonend = 0;
boolean startJson = false;
int status = WL_IDLE_STATUS;
#define JSON_BUFF_DIMENSION 5000
// One minute for testing. Should be 10 minutes per the API.
unsigned long lastConnectionTime = 1 * 60 * 1000; // last time you connected to the server
const unsigned long postInterval = 1 * 60 * 1000; // posting interval
//============== setup() ==============
void setup() {
Serial.begin(115200);
text.reserve(JSON_BUFF_DIMENSION);
WiFi.enableInsecureWEP();
WiFi.begin(ssid, pass);
Serial.println("connecting");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi Connected");
printWiFiStatus();
Serial.println(F("..............."));
lastConnectionTime = millis();
makehttpRequest();
}
//============== loop() ==============
void loop() {
if (millis() - lastConnectionTime > postInterval) {
lastConnectionTime = millis();
makehttpRequest();
}
}
// ============== printWiFiStatus ==============
// print Wifi status
void printWiFiStatus() {
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
//============== makeHttpRequest() ==============
// to request data from OWM
void makehttpRequest() {
int siz = 0; //Size of json string
client.stop();
if (client.connect(server, 80)) {
Serial.println();
Serial.println(F("connecting to OWM..."));
// send the HTTP PUT request:
client.println("GET /data/2.5/forecast?q=" + nameOfCity + "&APPID=" + apiKey + "&mode=json&units=imperial&cnt=2");
client.println("Host: api.openweathermap.org");
client.println("User-Agent: ArduinoWiFi/1.1");
client.println("Connection: close");
client.println();
unsigned long timeout = millis();
while (client.available() == 0) {
if (millis() - timeout > 5000) {
Serial.println(F(">>> Client Timeout !"));
client.stop();
return;
}
}
Serial.println(F("Reading json..."));
char c = 0;
while (client.available()) {
c = client.read();
Serial.print(c);
if (c == '{') {
startJson = true; // set startJson true to indicate json message has started
jsonend++; // +Count an opening brace
}
if (c == '}') {
jsonend--; // -Count a closing brace
}
if (startJson == true) {
text += c;
siz += 1; // Bump the string size
}
// if jsonend = 0 then we have have received equal number of curly braces
if (jsonend == 0 && startJson == true) {
Serial.println(F("Parsing json string"));
Serial.print(F("siz= "));
Serial.println(siz);
parseJson(text.c_str()); // parse
text = ""; // clear text string for the next time
startJson = false; // Indicate that a new message has not yet started
}
}
}
else {
// if no connection was made:
Serial.println(F("connection failed"));
return;
}
}
//============== parseJson() ==============
void parseJson(const char * jsonString) {
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;
DynamicJsonDocument doc(bufferSize);
DeserializationError error = deserializeJson(doc, jsonString);
if (error) {
Serial.print(F("deserializeJson() failed with code "));
Serial.println(error.c_str());
return;
}
JsonArray list = doc["list"];
JsonObject nowT = list[0];
JsonObject later = list[1];
// temperature and humidity
String city = doc["city"]["name"];
float tempNow = nowT["main"]["temp"];
float humidityNow = nowT["main"]["humidity"];
String weatherNow = nowT["weather"][0]["description"];
float tempLater = later["main"]["temp"];
float humidityLater = later["main"]["humidity"];
String weatherLater = later["weather"][0]["description"];
}