Error on API Integration and data request from AccuWeather

Hello!

I am integrating AccuWeather and MinuteCast in NodeMCU, I have got this code from the Example of AccuWeather API Example from GitHub and when I add all my credentials I get an error

here is the Code DIRECTLY from the example (No modifications)
I also get the errors from the example code too...

#include <JsonListener.h>
#include "AccuWeatherLibrary.h"

AccuweatherDailyData dataD[2];
AccuweatherHourlyData dataH;
AccuweatherCurrentData dataC;

Accuweather aw("api key goes here", 0, "en-us", true);

void setup() {
  Serial.begin(115200);
  WiFi.begin("WIFI_SSID", "WIFI_PASSWORD");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.println(".");
    delay(100);
  }
  Serial.println(String(ESP.getFreeHeap()));
  int timeStart = millis();
  //int ret = aw.getDaily(dataD,2);
  //int ret = aw.getHourly(&dataH, 1);
  int ret = aw.getCurrent(&dataC);
  
  if (ret != 0){
    Serial.println("ERROR");
    Serial.println(ret);
    return;
  }
  
  while (aw.continueDownload() > 0){
  }

  //print_dataD();
  //print_dataH();
  print_dataC();

  timeStart = millis() - timeStart;

  Serial.printf("Downloaded and parsed in %d ms\n", timeStart);
  Serial.println(String(ESP.getFreeHeap()));
  
}

void loop() {
  // put your main code here, to run repeatedly:

}

void print_dataC(){
  Serial.println(dataC.LocalObservationDateTime);
  Serial.println(dataC.EpochTime);
  Serial.println(dataC.WeatherText);
  Serial.println(dataC.WeatherIcon);
  Serial.println(dataC.IsDayTime);
  Serial.println(dataC.Temperature);
  Serial.println(dataC.RealFeelTemperature);
  Serial.println(dataC.RealFeelTemperatureShade);
  Serial.println(dataC.RelativeHumidity);
  Serial.println(dataC.WindDirection);
  Serial.println(dataC.WindSpeed);
  Serial.println(dataC.WindGustSpeed);
  Serial.println(dataC.UVIndex);
  Serial.println(dataC.UVIndexText);
  Serial.println(dataC.Visibility);
  Serial.println(dataC.CloudCover);
  Serial.println(dataC.Pressure);
}

void print_dataH(){
  Serial.println(dataH.DateTime);
  Serial.println(dataH.EpochDateTime);
  Serial.println(dataH.WeatherIcon);
  Serial.println(dataH.IconPhrase);
  Serial.println(dataH.IsDaylight);
  Serial.println(dataH.Temperature);
  Serial.println(dataH.RealFeelTemperature);
  Serial.println(dataH.WindSpeed);
  Serial.println(dataH.WindDirection);
  Serial.println(dataH.WindGustSpeed);
  Serial.println(dataH.RelativeHumidity);
  Serial.println(dataH.Visibility);
  Serial.println(dataH.UVIndex);
  Serial.println(dataH.UVIndexText);
  Serial.println(dataH.PrecipitationProbability);
  Serial.println(dataH.RainProbability);
  Serial.println(dataH.SnowProbability);
  Serial.println(dataH.IceProbability);
  Serial.println(dataH.TotalLiquid);
  Serial.println(dataH.Rain);
  Serial.println(dataH.Snow);
  Serial.println(dataH.Ice);
  Serial.println(dataH.CloudCover);
}

void print_dataD(){
    Serial.println("====DAY 1====");
  Serial.println(dataD[0].Date);
  Serial.println(dataD[0].TempMin);
  Serial.println(dataD[0].TempMax);
  Serial.println(dataD[0].RealFeelTempMin);
  Serial.println(dataD[0].RealFeelTempMax);
  Serial.println(dataD[0].HoursOfSun);
  Serial.println(dataD[0].EpochDate);
  Serial.println(dataD[0].SunRise);
  Serial.println(dataD[0].SunSet);
  Serial.println("====DAY:====");
  Serial.println(dataD[0].Day.IconPhrase);
  Serial.println(dataD[0].Day.LongPhrase);
  Serial.println(dataD[0].Day.Ice);
  Serial.println(dataD[0].Day.Rain);
  Serial.println(dataD[0].Day.RelativeHumidity);
  Serial.println(dataD[0].Day.Snow);
  Serial.println(dataD[0].Day.TotalLiquid);
  Serial.println(dataD[0].Day.Visibility);
  Serial.println(dataD[0].Day.WindGustSpeed);
  Serial.println(dataD[0].Day.WindSpeed);
  Serial.println(dataD[0].Day.WindDirection);
  Serial.println(dataD[0].Day.CloudCover);
  Serial.println(dataD[0].Day.IceProbability);
  Serial.println(dataD[0].Day.PrecipitationProbability);
  Serial.println(dataD[0].Day.RainProbability);
  Serial.println(dataD[0].Day.SnowProbability);
  Serial.println(dataD[0].Day.ThunderstormProbability);
  Serial.println(dataD[0].Day.WeatherIcon);
  Serial.println("====NIGHT:====");
  Serial.println(dataD[0].Night.IconPhrase);
  Serial.println(dataD[0].Night.LongPhrase);
  Serial.println(dataD[0].Night.Ice);
  Serial.println(dataD[0].Night.Rain);
  Serial.println(dataD[0].Night.RelativeHumidity);
  Serial.println(dataD[0].Night.Snow);
  Serial.println(dataD[0].Night.TotalLiquid);
  Serial.println(dataD[0].Night.Visibility);
  Serial.println(dataD[0].Night.WindGustSpeed);
  Serial.println(dataD[0].Night.WindSpeed);
  Serial.println(dataD[0].Night.WindDirection);
  Serial.println(dataD[0].Night.CloudCover);
  Serial.println(dataD[0].Night.IceProbability);
  Serial.println(dataD[0].Night.PrecipitationProbability);
  Serial.println(dataD[0].Night.RainProbability);
  Serial.println(dataD[0].Night.SnowProbability);
  Serial.println(dataD[0].Night.ThunderstormProbability);
  Serial.println(dataD[0].Night.WeatherIcon);
  Serial.println("====DAY 2====");
  Serial.println(dataD[1].Date);
  Serial.println(dataD[1].TempMin);
  Serial.println(dataD[1].TempMax);
  Serial.println(dataD[1].RealFeelTempMin);
  Serial.println(dataD[1].RealFeelTempMax);
  Serial.println(dataD[1].HoursOfSun);
  Serial.println(dataD[1].EpochDate);
  Serial.println(dataD[1].SunRise);
  Serial.println(dataD[1].SunSet);
  Serial.println("====DAY:====");
  Serial.println(dataD[1].Day.IconPhrase);
  Serial.println(dataD[1].Day.LongPhrase);
  Serial.println(dataD[1].Day.Ice);
  Serial.println(dataD[1].Day.Rain);
  Serial.println(dataD[1].Day.RelativeHumidity);
  Serial.println(dataD[1].Day.Snow);
  Serial.println(dataD[1].Day.TotalLiquid);
  Serial.println(dataD[1].Day.Visibility);
  Serial.println(dataD[1].Day.WindGustSpeed);
  Serial.println(dataD[1].Day.WindSpeed);
  Serial.println(dataD[1].Day.WindDirection);
  Serial.println(dataD[1].Day.CloudCover);
  Serial.println(dataD[1].Day.IceProbability);
  Serial.println(dataD[1].Day.PrecipitationProbability);
  Serial.println(dataD[1].Day.RainProbability);
  Serial.println(dataD[1].Day.SnowProbability);
  Serial.println(dataD[1].Day.ThunderstormProbability);
  Serial.println(dataD[1].Day.WeatherIcon);
  Serial.println("====NIGHT:====");
  Serial.println(dataD[1].Night.IconPhrase);
  Serial.println(dataD[1].Night.LongPhrase);
  Serial.println(dataD[1].Night.Ice);
  Serial.println(dataD[1].Night.Rain);
  Serial.println(dataD[1].Night.RelativeHumidity);
  Serial.println(dataD[1].Night.Snow);
  Serial.println(dataD[1].Night.TotalLiquid);
  Serial.println(dataD[1].Night.Visibility);
  Serial.println(dataD[1].Night.WindGustSpeed);
  Serial.println(dataD[1].Night.WindSpeed);
  Serial.println(dataD[1].Night.WindDirection);
  Serial.println(dataD[1].Night.CloudCover);
  Serial.println(dataD[1].Night.IceProbability);
  Serial.println(dataD[1].Night.PrecipitationProbability);
  Serial.println(dataD[1].Night.RainProbability);
  Serial.println(dataD[1].Night.SnowProbability);
  Serial.println(dataD[1].Night.ThunderstormProbability);
  Serial.println(dataD[1].Night.WeatherIcon);
}

Here is the error I am getting :point_down: :point_down: :point_down:

/Users/vishanamarnath/Documents/Arduino/libraries/AccuWeatherLibrary-master/AccuWeatherLibrary.cpp: In member function 'int Accuweather::getCurrent(AccuweatherCurrentData*)':
/Users/vishanamarnath/Documents/Arduino/libraries/AccuWeatherLibrary-master/AccuWeatherLibrary.cpp:581:15: error: call to 'HTTPClient::begin' declared with attribute error: obsolete API, use ::begin(WiFiClient, url)
  581 |     http.begin(url);
      |     ~~~~~~~~~~^~~~~
/Users/vishanamarnath/Documents/Arduino/libraries/AccuWeatherLibrary-master/AccuWeatherLibrary.cpp: In member function 'int Accuweather::getHourly(AccuweatherHourlyData*, int)':
/Users/vishanamarnath/Documents/Arduino/libraries/AccuWeatherLibrary-master/AccuWeatherLibrary.cpp:612:15: error: call to 'HTTPClient::begin' declared with attribute error: obsolete API, use ::begin(WiFiClient, url)
  612 |     http.begin(url);
      |     ~~~~~~~~~~^~~~~
/Users/vishanamarnath/Documents/Arduino/libraries/AccuWeatherLibrary-master/AccuWeatherLibrary.cpp: In member function 'int Accuweather::getDaily(AccuweatherDailyData*, int)':
/Users/vishanamarnath/Documents/Arduino/libraries/AccuWeatherLibrary-master/AccuWeatherLibrary.cpp:644:15: error: call to 'HTTPClient::begin' declared with attribute error: obsolete API, use ::begin(WiFiClient, url)
  644 |     http.begin(url);
      |     ~~~~~~~~~~^~~~~

exit status 1

Compilation error: exit status 1

Links for the library : https://github.com/jackmax/AccuWeatherLibrary

Any help will be truly appreciated
Vishan

The library is out of date. If they don't provide a newer one you will have to fix their library.

Hi @johnwasser

This is the new library I got...
Can you give me any idea of how I can fix that?

I am new to this AccuWeather library and API calls
Could you please help me with this?

Thank you
Vishan

AccuWeatherLibrary.cpp line 581
AccuWeatherLibrary.cpp line 612
AccuWeatherLibrary.cpp line 644
http.begin(url); obsolete API, use:
http.begin(<your WiFiClient object>, url);


#include <JsonListener.h>
#include <AccuWeatherLibrary.h>

AccuweatherDailyData dataD[2];
AccuweatherHourlyData dataH;
AccuweatherCurrentData dataC;

Accuweather aw("tVhZeddCMqPW9GgbAfadFSaAfcXm4T0X", 307525, "en-us", true);
void handleTEMP();

void setup() {
  Serial.begin(115200);
  WiFi.begin("vishan", "pswd123456");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.println(".");
    delay(100);
    http.begin("http://dataservice.accuweather.com/forecasts/v1/minute");
   
  }
  Serial.println(String(ESP.getFreeHeap()));
  int timeStart = millis();
  //int ret = aw.getDaily(dataD,2);
  //int ret = aw.getHourly(&dataH, 1);
  int ret = aw.getCurrent(&dataC);
  
  if (ret != 0){
    Serial.println("ERROR");
    Serial.println(ret);
    return;
  }
  
  while (aw.continueDownload() > 0){
  }

  //print_dataD();
  //print_dataH();
  print_dataC();

  timeStart = millis() - timeStart;

  Serial.printf("Downloaded and parsed in %d ms\n", timeStart);
  Serial.println(String(ESP.getFreeHeap()));
  
}

void loop() {
  // put your main code here, to run repeatedly:

}

void print_dataC(){
  Serial.println(dataC.LocalObservationDateTime);
  Serial.println(dataC.EpochTime);
  Serial.println(dataC.WeatherText);
  Serial.println(dataC.WeatherIcon);
  Serial.println(dataC.IsDayTime);
  Serial.println(dataC.Temperature);
  Serial.println(dataC.RealFeelTemperature);
  Serial.println(dataC.RealFeelTemperatureShade);
  Serial.println(dataC.RelativeHumidity);
  Serial.println(dataC.WindDirection);
  Serial.println(dataC.WindSpeed);
  Serial.println(dataC.WindGustSpeed);
  Serial.println(dataC.UVIndex);
  Serial.println(dataC.UVIndexText);
  Serial.println(dataC.Visibility);
  Serial.println(dataC.CloudCover);
  Serial.println(dataC.Pressure);
}

void print_dataH(){
  Serial.println(dataH.DateTime);
  Serial.println(dataH.EpochDateTime);
  Serial.println(dataH.WeatherIcon);
  Serial.println(dataH.IconPhrase);
  Serial.println(dataH.IsDaylight);
  Serial.println(dataH.Temperature);
  Serial.println(dataH.RealFeelTemperature);
  Serial.println(dataH.WindSpeed);
  Serial.println(dataH.WindDirection);
  Serial.println(dataH.WindGustSpeed);
  Serial.println(dataH.RelativeHumidity);
  Serial.println(dataH.Visibility);
  Serial.println(dataH.UVIndex);
  Serial.println(dataH.UVIndexText);
  Serial.println(dataH.PrecipitationProbability);
  Serial.println(dataH.RainProbability);
  Serial.println(dataH.SnowProbability);
  Serial.println(dataH.IceProbability);
  Serial.println(dataH.TotalLiquid);
  Serial.println(dataH.Rain);
  Serial.println(dataH.Snow);
  Serial.println(dataH.Ice);
  Serial.println(dataH.CloudCover);
}

void print_dataD(){
    Serial.println("====DAY 1====");
  Serial.println(dataD[0].Date);
  Serial.println(dataD[0].TempMin);
  Serial.println(dataD[0].TempMax);
  Serial.println(dataD[0].RealFeelTempMin);
  Serial.println(dataD[0].RealFeelTempMax);
  Serial.println(dataD[0].HoursOfSun);
  Serial.println(dataD[0].EpochDate);
  Serial.println(dataD[0].SunRise);
  Serial.println(dataD[0].SunSet);
  Serial.println("====DAY:====");
  Serial.println(dataD[0].Day.IconPhrase);
  Serial.println(dataD[0].Day.LongPhrase);
  Serial.println(dataD[0].Day.Ice);
  Serial.println(dataD[0].Day.Rain);
  Serial.println(dataD[0].Day.RelativeHumidity);
  Serial.println(dataD[0].Day.Snow);
  Serial.println(dataD[0].Day.TotalLiquid);
  Serial.println(dataD[0].Day.Visibility);
  Serial.println(dataD[0].Day.WindGustSpeed);
  Serial.println(dataD[0].Day.WindSpeed);
  Serial.println(dataD[0].Day.WindDirection);
  Serial.println(dataD[0].Day.CloudCover);
  Serial.println(dataD[0].Day.IceProbability);
  Serial.println(dataD[0].Day.PrecipitationProbability);
  Serial.println(dataD[0].Day.RainProbability);
  Serial.println(dataD[0].Day.SnowProbability);
  Serial.println(dataD[0].Day.ThunderstormProbability);
  Serial.println(dataD[0].Day.WeatherIcon);
  Serial.println("====NIGHT:====");
  Serial.println(dataD[0].Night.IconPhrase);
  Serial.println(dataD[0].Night.LongPhrase);
  Serial.println(dataD[0].Night.Ice);
  Serial.println(dataD[0].Night.Rain);
  Serial.println(dataD[0].Night.RelativeHumidity);
  Serial.println(dataD[0].Night.Snow);
  Serial.println(dataD[0].Night.TotalLiquid);
  Serial.println(dataD[0].Night.Visibility);
  Serial.println(dataD[0].Night.WindGustSpeed);
  Serial.println(dataD[0].Night.WindSpeed);
  Serial.println(dataD[0].Night.WindDirection);
  Serial.println(dataD[0].Night.CloudCover);
  Serial.println(dataD[0].Night.IceProbability);
  Serial.println(dataD[0].Night.PrecipitationProbability);
  Serial.println(dataD[0].Night.RainProbability);
  Serial.println(dataD[0].Night.SnowProbability);
  Serial.println(dataD[0].Night.ThunderstormProbability);
  Serial.println(dataD[0].Night.WeatherIcon);
  Serial.println("====DAY 2====");
  Serial.println(dataD[1].Date);
  Serial.println(dataD[1].TempMin);
  Serial.println(dataD[1].TempMax);
  Serial.println(dataD[1].RealFeelTempMin);
  Serial.println(dataD[1].RealFeelTempMax);
  Serial.println(dataD[1].HoursOfSun);
  Serial.println(dataD[1].EpochDate);
  Serial.println(dataD[1].SunRise);
  Serial.println(dataD[1].SunSet);
  Serial.println("====DAY:====");
  Serial.println(dataD[1].Day.IconPhrase);
  Serial.println(dataD[1].Day.LongPhrase);
  Serial.println(dataD[1].Day.Ice);
  Serial.println(dataD[1].Day.Rain);
  Serial.println(dataD[1].Day.RelativeHumidity);
  Serial.println(dataD[1].Day.Snow);
  Serial.println(dataD[1].Day.TotalLiquid);
  Serial.println(dataD[1].Day.Visibility);
  Serial.println(dataD[1].Day.WindGustSpeed);
  Serial.println(dataD[1].Day.WindSpeed);
  Serial.println(dataD[1].Day.WindDirection);
  Serial.println(dataD[1].Day.CloudCover);
  Serial.println(dataD[1].Day.IceProbability);
  Serial.println(dataD[1].Day.PrecipitationProbability);
  Serial.println(dataD[1].Day.RainProbability);
  Serial.println(dataD[1].Day.SnowProbability);
  Serial.println(dataD[1].Day.ThunderstormProbability);
  Serial.println(dataD[1].Day.WeatherIcon);
  Serial.println("====NIGHT:====");
  Serial.println(dataD[1].Night.IconPhrase);
  Serial.println(dataD[1].Night.LongPhrase);
  Serial.println(dataD[1].Night.Ice);
  Serial.println(dataD[1].Night.Rain);
  Serial.println(dataD[1].Night.RelativeHumidity);
  Serial.println(dataD[1].Night.Snow);
  Serial.println(dataD[1].Night.TotalLiquid);
  Serial.println(dataD[1].Night.Visibility);
  Serial.println(dataD[1].Night.WindGustSpeed);
  Serial.println(dataD[1].Night.WindSpeed);
  Serial.println(dataD[1].Night.WindDirection);
  Serial.println(dataD[1].Night.CloudCover);
  Serial.println(dataD[1].Night.IceProbability);
  Serial.println(dataD[1].Night.PrecipitationProbability);
  Serial.println(dataD[1].Night.RainProbability);
  Serial.println(dataD[1].Night.SnowProbability);
  Serial.println(dataD[1].Night.ThunderstormProbability);
  Serial.println(dataD[1].Night.WeatherIcon);
}

The Modified code. :point_up: :point_up: :arrow_up: :arrow_up:

The error :point_down: :point_down: :arrow_down: :arrow_down:

/Users/vishanamarnath/Documents/Arduino/AccuWeather_API_Example1/AccuWeather_API_Example1.ino: In function 'void setup()':
/Users/vishanamarnath/Documents/Arduino/AccuWeather_API_Example1/AccuWeather_API_Example1.ino:18:5: error: 'http' was not declared in this scope
   18 |     http.begin("http://dataservice.accuweather.com/forecasts/v1/minute");
      |     ^~~~

exit status 1

Compilation error: 'http' was not declared in this scope

I added it but still no luck.............

Vishan

Why are you using an object named http when you didn't create one, and why do it repeatdedly while waiting for the WiFi to connect? And why pass the URL to http.begin() when the library failed doing just that?

You probably need this somewhere:
`HTTPClient http;'

Show i use any other libraries if so... how I can use the codes for calling other API's from eg:Openweather and use it for AccuWeather

as they have given some documentations


Here is the link : AccuWeather APIs | MinuteCast® Forecasts By Latitude, Longitude

and I also found out that there are lots of tutorials based on OpenWeather API
but no tutorials for AccuWeather API integration

Is it possible to use the code made for OpenWeather and use it for AccuWeather as they are doing the same job.....I tried but I met with lots of errors

In the three places where the errors were reported, change:

    http.begin(URL);

to:

    WiFiClient client;
    http.begin(client, URL);

After that the example compiled without error for me.

I still get the same error as HTTP was not defined and what should I replace the 'client' with is it my wifi SSID?

That's because you put "http.begin(URL));" in your sketch. THAT LINE IS NOT IN THE ORIGINAL EXAMPLE PROGRAM.

Change ONLY the three places in AccuWeatherLibrary.cpp!

Could you please send me the code that worked for you?

Thanks
Vishan

Do I have to edit the library??

If possible could you please share me the code that compiled for you?

AccuWeather_API_Example.ino

#include <JsonListener.h>
#include "AccuWeatherLibrary.h"

AccuweatherDailyData dataD[2];
AccuweatherHourlyData dataH;
AccuweatherCurrentData dataC;

Accuweather aw("api key goes here", 0, "en-us", true);

void setup() {
  Serial.begin(115200);
  WiFi.begin("WIFI_SSID", "WIFI_PASSWORD");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.println(".");
    delay(100);
  }
  
  Serial.println(String(ESP.getFreeHeap()));
  
  int timeStart = millis();
  //int ret = aw.getDaily(dataD,2);
  //int ret = aw.getHourly(&dataH, 1);
  int ret = aw.getCurrent(&dataC);
  
  if (ret != 0){
    Serial.println("ERROR");
    Serial.println(ret);
    return;
  }
  
  while (aw.continueDownload() > 0){
  }

  //print_dataD();
  //print_dataH();
  print_dataC();

  timeStart = millis() - timeStart;

  Serial.printf("Downloaded and parsed in %d ms\n", timeStart);
  Serial.println(String(ESP.getFreeHeap()));
  
}

void loop() {
  // put your main code here, to run repeatedly:

}

void print_dataC(){
  Serial.println(dataC.LocalObservationDateTime);
  Serial.println(dataC.EpochTime);
  Serial.println(dataC.WeatherText);
  Serial.println(dataC.WeatherIcon);
  Serial.println(dataC.IsDayTime);
  Serial.println(dataC.Temperature);
  Serial.println(dataC.RealFeelTemperature);
  Serial.println(dataC.RealFeelTemperatureShade);
  Serial.println(dataC.RelativeHumidity);
  Serial.println(dataC.WindDirection);
  Serial.println(dataC.WindSpeed);
  Serial.println(dataC.WindGustSpeed);
  Serial.println(dataC.UVIndex);
  Serial.println(dataC.UVIndexText);
  Serial.println(dataC.Visibility);
  Serial.println(dataC.CloudCover);
  Serial.println(dataC.Pressure);
}

void print_dataH(){
  Serial.println(dataH.DateTime);
  Serial.println(dataH.EpochDateTime);
  Serial.println(dataH.WeatherIcon);
  Serial.println(dataH.IconPhrase);
  Serial.println(dataH.IsDaylight);
  Serial.println(dataH.Temperature);
  Serial.println(dataH.RealFeelTemperature);
  Serial.println(dataH.WindSpeed);
  Serial.println(dataH.WindDirection);
  Serial.println(dataH.WindGustSpeed);
  Serial.println(dataH.RelativeHumidity);
  Serial.println(dataH.Visibility);
  Serial.println(dataH.UVIndex);
  Serial.println(dataH.UVIndexText);
  Serial.println(dataH.PrecipitationProbability);
  Serial.println(dataH.RainProbability);
  Serial.println(dataH.SnowProbability);
  Serial.println(dataH.IceProbability);
  Serial.println(dataH.TotalLiquid);
  Serial.println(dataH.Rain);
  Serial.println(dataH.Snow);
  Serial.println(dataH.Ice);
  Serial.println(dataH.CloudCover);
}

void print_dataD(){
    Serial.println("====DAY 1====");
  Serial.println(dataD[0].Date);
  Serial.println(dataD[0].TempMin);
  Serial.println(dataD[0].TempMax);
  Serial.println(dataD[0].RealFeelTempMin);
  Serial.println(dataD[0].RealFeelTempMax);
  Serial.println(dataD[0].HoursOfSun);
  Serial.println(dataD[0].EpochDate);
  Serial.println(dataD[0].SunRise);
  Serial.println(dataD[0].SunSet);
  Serial.println("====DAY:====");
  Serial.println(dataD[0].Day.IconPhrase);
  Serial.println(dataD[0].Day.LongPhrase);
  Serial.println(dataD[0].Day.Ice);
  Serial.println(dataD[0].Day.Rain);
  Serial.println(dataD[0].Day.RelativeHumidity);
  Serial.println(dataD[0].Day.Snow);
  Serial.println(dataD[0].Day.TotalLiquid);
  Serial.println(dataD[0].Day.Visibility);
  Serial.println(dataD[0].Day.WindGustSpeed);
  Serial.println(dataD[0].Day.WindSpeed);
  Serial.println(dataD[0].Day.WindDirection);
  Serial.println(dataD[0].Day.CloudCover);
  Serial.println(dataD[0].Day.IceProbability);
  Serial.println(dataD[0].Day.PrecipitationProbability);
  Serial.println(dataD[0].Day.RainProbability);
  Serial.println(dataD[0].Day.SnowProbability);
  Serial.println(dataD[0].Day.ThunderstormProbability);
  Serial.println(dataD[0].Day.WeatherIcon);
  Serial.println("====NIGHT:====");
  Serial.println(dataD[0].Night.IconPhrase);
  Serial.println(dataD[0].Night.LongPhrase);
  Serial.println(dataD[0].Night.Ice);
  Serial.println(dataD[0].Night.Rain);
  Serial.println(dataD[0].Night.RelativeHumidity);
  Serial.println(dataD[0].Night.Snow);
  Serial.println(dataD[0].Night.TotalLiquid);
  Serial.println(dataD[0].Night.Visibility);
  Serial.println(dataD[0].Night.WindGustSpeed);
  Serial.println(dataD[0].Night.WindSpeed);
  Serial.println(dataD[0].Night.WindDirection);
  Serial.println(dataD[0].Night.CloudCover);
  Serial.println(dataD[0].Night.IceProbability);
  Serial.println(dataD[0].Night.PrecipitationProbability);
  Serial.println(dataD[0].Night.RainProbability);
  Serial.println(dataD[0].Night.SnowProbability);
  Serial.println(dataD[0].Night.ThunderstormProbability);
  Serial.println(dataD[0].Night.WeatherIcon);
  Serial.println("====DAY 2====");
  Serial.println(dataD[1].Date);
  Serial.println(dataD[1].TempMin);
  Serial.println(dataD[1].TempMax);
  Serial.println(dataD[1].RealFeelTempMin);
  Serial.println(dataD[1].RealFeelTempMax);
  Serial.println(dataD[1].HoursOfSun);
  Serial.println(dataD[1].EpochDate);
  Serial.println(dataD[1].SunRise);
  Serial.println(dataD[1].SunSet);
  Serial.println("====DAY:====");
  Serial.println(dataD[1].Day.IconPhrase);
  Serial.println(dataD[1].Day.LongPhrase);
  Serial.println(dataD[1].Day.Ice);
  Serial.println(dataD[1].Day.Rain);
  Serial.println(dataD[1].Day.RelativeHumidity);
  Serial.println(dataD[1].Day.Snow);
  Serial.println(dataD[1].Day.TotalLiquid);
  Serial.println(dataD[1].Day.Visibility);
  Serial.println(dataD[1].Day.WindGustSpeed);
  Serial.println(dataD[1].Day.WindSpeed);
  Serial.println(dataD[1].Day.WindDirection);
  Serial.println(dataD[1].Day.CloudCover);
  Serial.println(dataD[1].Day.IceProbability);
  Serial.println(dataD[1].Day.PrecipitationProbability);
  Serial.println(dataD[1].Day.RainProbability);
  Serial.println(dataD[1].Day.SnowProbability);
  Serial.println(dataD[1].Day.ThunderstormProbability);
  Serial.println(dataD[1].Day.WeatherIcon);
  Serial.println("====NIGHT:====");
  Serial.println(dataD[1].Night.IconPhrase);
  Serial.println(dataD[1].Night.LongPhrase);
  Serial.println(dataD[1].Night.Ice);
  Serial.println(dataD[1].Night.Rain);
  Serial.println(dataD[1].Night.RelativeHumidity);
  Serial.println(dataD[1].Night.Snow);
  Serial.println(dataD[1].Night.TotalLiquid);
  Serial.println(dataD[1].Night.Visibility);
  Serial.println(dataD[1].Night.WindGustSpeed);
  Serial.println(dataD[1].Night.WindSpeed);
  Serial.println(dataD[1].Night.WindDirection);
  Serial.println(dataD[1].Night.CloudCover);
  Serial.println(dataD[1].Night.IceProbability);
  Serial.println(dataD[1].Night.PrecipitationProbability);
  Serial.println(dataD[1].Night.RainProbability);
  Serial.println(dataD[1].Night.SnowProbability);
  Serial.println(dataD[1].Night.ThunderstormProbability);
  Serial.println(dataD[1].Night.WeatherIcon);
}

AccuWeatherLibrary.cpp:

#include "AccuWeatherLibrary.h"
#include "JsonListener.h"

#define SIZE_OF_CONST_TABLE(x) sizeof(x)/sizeof(x[0])
#define STACK_HAS_SUFFIX(x) stackSuffix(x, SIZE_OF_CONST_TABLE(x))
/*
 *  Parser constants
 */
//A map to transform strings into tokens
static const std::map<const String, const AccuParserTokens> stringToTokenMap = {
    { "CloudCover", ACCUPARSERCloudCover },
    { "DailyForecasts", ACCUPARSERDailyForecasts },
    { "Date", ACCUPARSERDate },
    { "DateTime", ACCUPARSERDateTime },
    { "Day", ACCUPARSERDay },
    { "Degrees", ACCUPARSERDegrees },
    { "Direction", ACCUPARSERDirection },
    { "English", ACCUPARSEREnglish },
    { "EpochDate", ACCUPARSEREpochDate },
    { "EpochDateTime", ACCUPARSEREpochDateTime },
    { "EpochRise", ACCUPARSEREpochRise },
    { "EpochSet", ACCUPARSEREpochSet },
    { "EpochTime", ACCUPARSEREpochTime },
    { "HoursOfSun", ACCUPARSERHoursOfSun },
    { "Ice", ACCUPARSERIce },
    { "IceProbability", ACCUPARSERIceProbability },
    { "Icon", ACCUPARSERIcon },
    { "IconPhrase", ACCUPARSERIconPhrase },
    { "Imperial", ACCUPARSERImperial },
    { "IsDaylight", ACCUPARSERIsDaylight },
    { "IsDayTime", ACCUPARSERIsDayTime },
    { "LocalObservationDateTime", ACCUPARSERLocalObservationDateTime },
    { "LongPhrase", ACCUPARSERLongPhrase },
    { "Maximum", ACCUPARSERMaximum },
    { "Metric", ACCUPARSERMetric },
    { "Minimum", ACCUPARSERMinimum },
    { "Moon", ACCUPARSERMoon },
    { "Night", ACCUPARSERNight },
    { "Precip1hr", ACCUPARSERPrecip1hr },
    { "PrecipitationProbability", ACCUPARSERPrecipitationProbability },
    { "Pressure", ACCUPARSERPressure },
    { "Rain", ACCUPARSERRain },
    { "RainProbability", ACCUPARSERRainProbability },
    { "RealFeelTemperature", ACCUPARSERRealFeelTemperature },
    { "RealFeelTemperatureShade", ACCUPARSERRealFeelTemperatureShade },
    { "RelativeHumidity", ACCUPARSERRelativeHumidity },
    { "ShortPhrase", ACCUPARSERShortPhrase },
    { "Snow", ACCUPARSERSnow },
    { "SnowProbability", ACCUPARSERSnowProbability },
    { "Speed", ACCUPARSERSpeed },
    { "Sun", ACCUPARSERSun },
    { "Temperature", ACCUPARSERTemperature },
    { "ThunderstormProbability", ACCUPARSERThunderstormProbability },
    { "TotalLiquid", ACCUPARSERTotalLiquid },
    { "Unit", ACCUPARSERUnit },
    { "UVIndex", ACCUPARSERUVIndex },
    { "UVIndexText", ACCUPARSERUVIndexText },
    { "Value", ACCUPARSERValue },
    { "Visibility", ACCUPARSERVisibility },
    { "WeatherIcon", ACCUPARSERWeatherIcon },
    { "WeatherText", ACCUPARSERWeatherText },
    { "Wind", ACCUPARSERWind },
    { "WindGust", ACCUPARSERWindGust },
};

//Arrays of stack suffixes - if the stack has this suffix, this means that this piece of data can be obtained
static const AccuParserTokens LocalObservationDateTime_suffix[] = {ACCUPARSERLocalObservationDateTime};
static const AccuParserTokens DateTime_suffix[] = {ACCUPARSERDateTime};
static const AccuParserTokens EpochTime_suffix[] = {ACCUPARSEREpochTime};
static const AccuParserTokens EpochDateTime_suffix[] = {ACCUPARSEREpochDateTime};
static const AccuParserTokens Date_suffix[] = {ACCUPARSERDate};
static const AccuParserTokens EpochDate_suffix[] = {ACCUPARSEREpochDate};
static const AccuParserTokens HoursOfSun_suffix[] = {ACCUPARSERHoursOfSun};
static const AccuParserTokens WeatherText_suffix[] = {ACCUPARSERWeatherText};
static const AccuParserTokens WeatherIcon_suffix[] = {ACCUPARSERWeatherIcon};
static const AccuParserTokens Icon_suffix[] = {ACCUPARSERIcon};
static const AccuParserTokens IconPhrase_suffix[] = {ACCUPARSERIconPhrase};
static const AccuParserTokens LongPhrase_suffix[] = {ACCUPARSERLongPhrase};
static const AccuParserTokens IsDayTime_suffix[] = {ACCUPARSEREpochTime};
static const AccuParserTokens IsDaylight_suffix[] = {ACCUPARSERIsDaylight};
static const AccuParserTokens RelativeHumidity_suffix[] = {ACCUPARSERRelativeHumidity};
static const AccuParserTokens WindDirection_suffix[] = {ACCUPARSERWind, ACCUPARSERObject, ACCUPARSERDirection, ACCUPARSERObject, ACCUPARSERDegrees};
static const AccuParserTokens UVIndex_suffix[] = {ACCUPARSERUVIndex};
static const AccuParserTokens UVIndexText_suffix[] = {ACCUPARSERUVIndexText};
static const AccuParserTokens CloudCover_suffix[] = {ACCUPARSERCloudCover};

static const AccuParserTokens UnitTemperature_suffix[] = {ACCUPARSERTemperature, ACCUPARSERObject, ACCUPARSERUnitPlaceholder, ACCUPARSERObject, ACCUPARSERValue};
static const AccuParserTokens RealFeelUnitTemperature_suffix[] = {ACCUPARSERRealFeelTemperature, ACCUPARSERObject, ACCUPARSERUnitPlaceholder, ACCUPARSERObject, ACCUPARSERValue};
static const AccuParserTokens RealFeelUnitTemperatureShade_suffix[] = {ACCUPARSERRealFeelTemperatureShade, ACCUPARSERObject, ACCUPARSERUnitPlaceholder, ACCUPARSERObject, ACCUPARSERValue};
static const AccuParserTokens WindUnitSpeed_suffix[] = {ACCUPARSERWind, ACCUPARSERObject, ACCUPARSERSpeed, ACCUPARSERObject, ACCUPARSERUnitPlaceholder, ACCUPARSERObject, ACCUPARSERValue};
static const AccuParserTokens WindGustUnitSpeed_suffix[] = {ACCUPARSERWindGust, ACCUPARSERObject, ACCUPARSERSpeed, ACCUPARSERObject, ACCUPARSERUnitPlaceholder, ACCUPARSERObject, ACCUPARSERValue};
static const AccuParserTokens UnitPressure_suffix[] = {ACCUPARSERPressure, ACCUPARSERObject, ACCUPARSERUnitPlaceholder, ACCUPARSERObject, ACCUPARSERValue};
static const AccuParserTokens UnitVisibility_suffix[] = {ACCUPARSERVisibility, ACCUPARSERObject, ACCUPARSERUnitPlaceholder, ACCUPARSERObject, ACCUPARSERValue};

static const AccuParserTokens Temperature_suffix[] = {ACCUPARSERTemperature, ACCUPARSERObject, ACCUPARSERValue};
static const AccuParserTokens RealFeelTemperature_suffix[] = {ACCUPARSERRealFeelTemperature, ACCUPARSERObject, ACCUPARSERValue};
static const AccuParserTokens RealFeelTemperatureShade_suffix[] = {ACCUPARSERRealFeelTemperatureShade, ACCUPARSERObject, ACCUPARSERValue};
static const AccuParserTokens WindSpeed_suffix[] = {ACCUPARSERWind, ACCUPARSERObject, ACCUPARSERSpeed, ACCUPARSERObject, ACCUPARSERValue};
static const AccuParserTokens WindGustSpeed_suffix[] = {ACCUPARSERWindGust, ACCUPARSERObject, ACCUPARSERSpeed, ACCUPARSERObject, ACCUPARSERValue};
static const AccuParserTokens Pressure_suffix[] = {ACCUPARSERPressure, ACCUPARSERObject, ACCUPARSERValue};
static const AccuParserTokens Visibility_suffix[] = {ACCUPARSERVisibility, ACCUPARSERObject, ACCUPARSERValue};

static const AccuParserTokens TempMin_suffix[] = {ACCUPARSERTemperature, ACCUPARSERObject, ACCUPARSERMinimum, ACCUPARSERObject, ACCUPARSERValue};
static const AccuParserTokens RealFeelTempMin_suffix[] = {ACCUPARSERRealFeelTemperature, ACCUPARSERObject, ACCUPARSERMinimum, ACCUPARSERObject, ACCUPARSERValue};
static const AccuParserTokens TempMax_suffix[] = {ACCUPARSERTemperature, ACCUPARSERObject, ACCUPARSERMaximum, ACCUPARSERObject, ACCUPARSERValue};
static const AccuParserTokens RealFeelTempMax_suffix[] = {ACCUPARSERRealFeelTemperature, ACCUPARSERObject, ACCUPARSERMaximum, ACCUPARSERObject, ACCUPARSERValue};

static const AccuParserTokens SunRise_suffix[] = {ACCUPARSERSun, ACCUPARSERObject, ACCUPARSEREpochRise};
static const AccuParserTokens SunSet_suffix[] = {ACCUPARSERSun, ACCUPARSERObject, ACCUPARSEREpochSet};

static const AccuParserTokens PrecipitationProbability_suffix[] = {ACCUPARSERPrecipitationProbability};
static const AccuParserTokens ThunderstormProbability_suffix[] = {ACCUPARSERThunderstormProbability};
static const AccuParserTokens RainProbability_suffix[] = {ACCUPARSERRainProbability};
static const AccuParserTokens SnowProbability_suffix[] = {ACCUPARSERSnowProbability};
static const AccuParserTokens IceProbability_suffix[] = {ACCUPARSERIceProbability};
static const AccuParserTokens TotalLiquid_suffix[] = {ACCUPARSERTotalLiquid, ACCUPARSERObject, ACCUPARSERValue};
static const AccuParserTokens Rain_suffix[] = {ACCUPARSERRain, ACCUPARSERObject, ACCUPARSERValue};
static const AccuParserTokens Snow_suffix[] = {ACCUPARSERSnow, ACCUPARSERObject, ACCUPARSERValue};
static const AccuParserTokens Ice_suffix[] = {ACCUPARSERIce, ACCUPARSERObject, ACCUPARSERValue};

static const AccuParserTokens baseList_suffix[] = {ACCUPARSERBase, ACCUPARSERList, ACCUPARSERObject};
static const AccuParserTokens dailyForecastsList_suffix[] = {ACCUPARSERBase, ACCUPARSERObject, ACCUPARSERDailyForecasts, ACCUPARSERList, ACCUPARSERObject};

/*
 *  Parser base class
 */
AccuweatherParser::AccuweatherParser(int maxListLength_, bool isMetric_){
    maxListLength = maxListLength_;
    isMetric = isMetric_;
}

void AccuweatherParser::startDocument() {
    tokenStack.push_back(ACCUPARSERBase);
}

void AccuweatherParser::endDocument() {
  if (tokenStack.back() != ACCUPARSERBase){
        Serial.println(F("ERROR: Document token not found"));
    }
    popAllKeys();
}

void AccuweatherParser::key(String key) {
    if (baseListIdx >= maxListLength){
        return;
    }
    auto it = stringToTokenMap.find(key);
    if (it != stringToTokenMap.end()){
        tokenStack.push_back(it->second);
    }
    else {
        tokenStack.push_back(ACCUPARSERUnknown);
    }
}

void AccuweatherParser::value(String value) {
    if (baseListIdx >= maxListLength){
        return;
    }
    Serial.println("value: " + value);
    popAllKeys();
}

void AccuweatherParser::startArray() {
    tokenStack.push_back(ACCUPARSERList);
}

void AccuweatherParser::endArray() {
    if (tokenStack.back() != ACCUPARSERList){
        Serial.println(F("ERROR: List token not found"));
    }
    tokenStack.pop_back();

    popAllKeys();
}

void AccuweatherParser::startObject() {
    tokenStack.push_back(ACCUPARSERObject);
    if (STACK_HAS_SUFFIX(baseList_suffix)){
        baseListIdx++;
    }
}

void AccuweatherParser::endObject() {
    if (tokenStack.back() != ACCUPARSERObject){
        Serial.println(F("ERROR: Object token not found"));
    }
    tokenStack.pop_back();

    popAllKeys();
}

void AccuweatherParser::whitespace(char c) {
    //ignore
}

//Some housekeeping functions
void AccuweatherParser::DEBUG_printStack(){
    for (auto it = tokenStack.begin() ; it != tokenStack.end(); ++it){
        Serial.print(">");
        Serial.print(*it);
    }
    Serial.println("*");
}

bool AccuweatherParser::stackSuffix(const AccuParserTokens suffix[], int suffix_len){
    int stackSize = tokenStack.size();
    if (stackSize < suffix_len){
        return false;
    }
    if (suffix_len == 0){
        return true;
    }
    do {
        stackSize--;
        suffix_len--;
        if (tokenStack[stackSize] != suffix[suffix_len]){
            if (suffix[suffix_len] == ACCUPARSERUnitPlaceholder){
                if (isMetric){
                    if (tokenStack[stackSize] != ACCUPARSERMetric){
                        return false;
                    }
                }
                else {
                    if (tokenStack[stackSize] != ACCUPARSERImperial){
                        return false;
                    }
                }
            }
            else {
                return false;
            }
        }
    }
    while (stackSize > 0 && suffix_len > 0);
    return true;
}

bool AccuweatherParser::stackContains(const AccuParserTokens token){
    for (auto it = tokenStack.rbegin(); it != tokenStack.rend(); it++)
        if (*it == token)
            return true;
    return false;
}

void AccuweatherParser::popAllKeys(){
    while (!(tokenStack.back() == ACCUPARSERObject || tokenStack.back() == ACCUPARSERList || tokenStack.back() == ACCUPARSERBase)){
        tokenStack.pop_back();
    }
}

/*
 *  Parsers for specific endpoints
 */
AccuweatherCurrentParser::AccuweatherCurrentParser(AccuweatherCurrentData* data_ptr_, bool isMetric_) : AccuweatherParser(1, isMetric_){
    data_ptr = data_ptr_;
}

void AccuweatherCurrentParser::value(String value){
    if (baseListIdx >= maxListLength){
        return;
    }

    if (STACK_HAS_SUFFIX(LocalObservationDateTime_suffix)) {
        data_ptr->LocalObservationDateTime = value;
    }
    else if (STACK_HAS_SUFFIX(EpochTime_suffix)){
        data_ptr->EpochTime = value.toInt();
    }
    else if (STACK_HAS_SUFFIX(WeatherText_suffix)){
        data_ptr->WeatherText = value;
    }
    else if (STACK_HAS_SUFFIX(WeatherIcon_suffix)){
        data_ptr->WeatherIcon = value.toInt();
    }
    else if (STACK_HAS_SUFFIX(IsDayTime_suffix)){
        data_ptr->IsDayTime = value == "true";
    }
    else if (STACK_HAS_SUFFIX(UnitTemperature_suffix)){
        data_ptr->Temperature = value.toFloat();
    }
    else if (STACK_HAS_SUFFIX(RealFeelUnitTemperature_suffix)){
        data_ptr->RealFeelTemperature = value.toFloat();
    }
    else if (STACK_HAS_SUFFIX(RealFeelUnitTemperatureShade_suffix)){
        data_ptr->RealFeelTemperatureShade = value.toFloat();
    }
    else if (STACK_HAS_SUFFIX(RelativeHumidity_suffix)){
        data_ptr->RelativeHumidity = value.toFloat();
    }
    else if (STACK_HAS_SUFFIX(WindDirection_suffix)){
        data_ptr->WindDirection = value.toInt();
    }
    else if (STACK_HAS_SUFFIX(WindUnitSpeed_suffix)){
        data_ptr->WindSpeed = value.toFloat();
    }
    else if (STACK_HAS_SUFFIX(WindGustUnitSpeed_suffix)){
        data_ptr->WindGustSpeed = value.toFloat();
    }
    else if (STACK_HAS_SUFFIX(UVIndex_suffix)){
        data_ptr->UVIndex = value.toInt();
    }
    else if (STACK_HAS_SUFFIX(UVIndexText_suffix)){
        data_ptr->UVIndexText = value;
    }
    else if (STACK_HAS_SUFFIX(UnitVisibility_suffix)){
        data_ptr->Visibility = value.toFloat();
    }
    else if (STACK_HAS_SUFFIX(CloudCover_suffix)){
        data_ptr->CloudCover = value.toFloat();
    }
    else if (STACK_HAS_SUFFIX(UnitPressure_suffix)){
        data_ptr->Pressure = value.toFloat();
    }
    
    popAllKeys();
}

AccuweatherHourlyParser::AccuweatherHourlyParser(AccuweatherHourlyData* data_ptr_, int maxListLength_) : AccuweatherParser(maxListLength_){
    data_ptr = data_ptr_;
}

void AccuweatherHourlyParser::value(String value){
    if (baseListIdx >= maxListLength){
        return;
    }

    if (STACK_HAS_SUFFIX(DateTime_suffix)) {
        data_ptr[baseListIdx].DateTime = value;
    }
    else if (STACK_HAS_SUFFIX(EpochDateTime_suffix)) {
        data_ptr[baseListIdx].EpochDateTime = value.toInt();
    }
    else if (STACK_HAS_SUFFIX(WeatherIcon_suffix)) {
        data_ptr[baseListIdx].WeatherIcon = value.toInt();
    }
    else if (STACK_HAS_SUFFIX(IconPhrase_suffix)) {
        data_ptr[baseListIdx].IconPhrase = value;
    }
    else if (STACK_HAS_SUFFIX(IsDaylight_suffix)) {
        data_ptr[baseListIdx].IsDaylight = value == "true";
    }
    else if (STACK_HAS_SUFFIX(Temperature_suffix)) {
        data_ptr[baseListIdx].Temperature = value.toFloat();
    }
    else if (STACK_HAS_SUFFIX(RealFeelTemperature_suffix)) {
        data_ptr[baseListIdx].RealFeelTemperature = value.toFloat();
    }
    else if (STACK_HAS_SUFFIX(WindSpeed_suffix)) {
        data_ptr[baseListIdx].WindSpeed = value.toFloat();
    }
    else if (STACK_HAS_SUFFIX(WindDirection_suffix)) {
        data_ptr[baseListIdx].WindDirection = value.toInt();
    }
    else if (STACK_HAS_SUFFIX(WindGustSpeed_suffix)) {
        data_ptr[baseListIdx].WindGustSpeed = value.toFloat();
    }
    else if (STACK_HAS_SUFFIX(RelativeHumidity_suffix)) {
        data_ptr[baseListIdx].RelativeHumidity = value.toFloat();
    }
    else if (STACK_HAS_SUFFIX(Visibility_suffix)) {
        data_ptr[baseListIdx].Visibility = value.toFloat();
    }
    else if (STACK_HAS_SUFFIX(UVIndex_suffix)) {
        data_ptr[baseListIdx].UVIndex = value.toInt();
    }
    else if (STACK_HAS_SUFFIX(UVIndexText_suffix)) {
        data_ptr[baseListIdx].UVIndexText = value;
    }
    else if (STACK_HAS_SUFFIX(PrecipitationProbability_suffix)) {
        data_ptr[baseListIdx].PrecipitationProbability = value.toInt();
    }
    else if (STACK_HAS_SUFFIX(RainProbability_suffix)) {
        data_ptr[baseListIdx].RainProbability = value.toInt();
    }
    else if (STACK_HAS_SUFFIX(SnowProbability_suffix)) {
        data_ptr[baseListIdx].SnowProbability = value.toInt();
    }
    else if (STACK_HAS_SUFFIX(IceProbability_suffix)) {
        data_ptr[baseListIdx].IceProbability = value.toInt();
    }
    else if (STACK_HAS_SUFFIX(TotalLiquid_suffix)) {
        data_ptr[baseListIdx].TotalLiquid = value.toFloat();
    }
    else if (STACK_HAS_SUFFIX(Rain_suffix)) {
        data_ptr[baseListIdx].Rain = value.toFloat();
    }
    else if (STACK_HAS_SUFFIX(Snow_suffix)) {
        data_ptr[baseListIdx].Snow = value.toFloat();
    }
    else if (STACK_HAS_SUFFIX(Ice_suffix)) {
        data_ptr[baseListIdx].Ice = value.toFloat();
    }
    else if (STACK_HAS_SUFFIX(CloudCover_suffix)) {
        data_ptr[baseListIdx].CloudCover = value.toInt();
    }

    popAllKeys();
}

AccuweatherDailyParser::AccuweatherDailyParser(AccuweatherDailyData* data_ptr_, int maxListLength_) : AccuweatherParser(maxListLength_){
    data_ptr = data_ptr_;
}

void AccuweatherDailyParser::startObject() {
    tokenStack.push_back(ACCUPARSERObject);
    if (STACK_HAS_SUFFIX(dailyForecastsList_suffix)){
        baseListIdx++;
    }
}

void AccuweatherDailyParser::value(String value){
    if (baseListIdx >= maxListLength){
        return;
    }

    if (STACK_HAS_SUFFIX(Date_suffix)) {
        data_ptr[baseListIdx].Date = value;
    }
    else if (STACK_HAS_SUFFIX(TempMin_suffix)) {
        data_ptr[baseListIdx].TempMin = value.toFloat();
    }
    else if (STACK_HAS_SUFFIX(TempMax_suffix)) {
        data_ptr[baseListIdx].TempMax = value.toFloat();
    }
    else if (STACK_HAS_SUFFIX(RealFeelTempMin_suffix)) {
        data_ptr[baseListIdx].RealFeelTempMin = value.toFloat();
    }
    else if (STACK_HAS_SUFFIX(RealFeelTempMax_suffix)) {
        data_ptr[baseListIdx].RealFeelTempMax = value.toFloat();
    }
    else if (STACK_HAS_SUFFIX(HoursOfSun_suffix)) {
        data_ptr[baseListIdx].HoursOfSun = value.toFloat();
    }
    else if (STACK_HAS_SUFFIX(EpochDate_suffix)) {
        data_ptr[baseListIdx].EpochDate = value.toInt();
    }
    else if (STACK_HAS_SUFFIX(SunRise_suffix)) {
        data_ptr[baseListIdx].SunRise = value.toInt();
    }
    else if (STACK_HAS_SUFFIX(SunSet_suffix)) {
        data_ptr[baseListIdx].SunSet = value.toInt();
    }
    else if (STACK_HAS_SUFFIX(IconPhrase_suffix)) {
        if (stackContains(ACCUPARSERDay))
            data_ptr[baseListIdx].Day.IconPhrase = value;
        else if (stackContains(ACCUPARSERNight))
            data_ptr[baseListIdx].Night.IconPhrase = value;

    }
    else if (STACK_HAS_SUFFIX(LongPhrase_suffix)) {
        if (stackContains(ACCUPARSERDay))
            data_ptr[baseListIdx].Day.LongPhrase = value;
        else if (stackContains(ACCUPARSERNight))
            data_ptr[baseListIdx].Night.LongPhrase = value;

    }
    else if (STACK_HAS_SUFFIX(Ice_suffix)) {
        if (stackContains(ACCUPARSERDay))
            data_ptr[baseListIdx].Day.Ice = value.toFloat();
        else if (stackContains(ACCUPARSERNight))
            data_ptr[baseListIdx].Night.Ice = value.toFloat();

    }
    else if (STACK_HAS_SUFFIX(Rain_suffix)) {
        if (stackContains(ACCUPARSERDay))
            data_ptr[baseListIdx].Day.Rain = value.toFloat();
        else if (stackContains(ACCUPARSERNight))
            data_ptr[baseListIdx].Night.Rain = value.toFloat();

    }
    else if (STACK_HAS_SUFFIX(RelativeHumidity_suffix)) {
        if (stackContains(ACCUPARSERDay))
            data_ptr[baseListIdx].Day.RelativeHumidity = value.toFloat();
        else if (stackContains(ACCUPARSERNight))
            data_ptr[baseListIdx].Night.RelativeHumidity = value.toFloat();

    }
    else if (STACK_HAS_SUFFIX(Snow_suffix)) {
        if (stackContains(ACCUPARSERDay))
            data_ptr[baseListIdx].Day.Snow = value.toFloat();
        else if (stackContains(ACCUPARSERNight))
            data_ptr[baseListIdx].Night.Snow = value.toFloat();

    }
    else if (STACK_HAS_SUFFIX(TotalLiquid_suffix)) {
        if (stackContains(ACCUPARSERDay))
            data_ptr[baseListIdx].Day.TotalLiquid = value.toFloat();
        else if (stackContains(ACCUPARSERNight))
            data_ptr[baseListIdx].Night.TotalLiquid = value.toFloat();

    }
    else if (STACK_HAS_SUFFIX(Visibility_suffix)) {
        if (stackContains(ACCUPARSERDay))
            data_ptr[baseListIdx].Day.Visibility = value.toFloat();
        else if (stackContains(ACCUPARSERNight))
            data_ptr[baseListIdx].Night.Visibility = value.toFloat();

    }
    else if (STACK_HAS_SUFFIX(WindGustSpeed_suffix)) {
        if (stackContains(ACCUPARSERDay))
            data_ptr[baseListIdx].Day.WindGustSpeed = value.toFloat();
        else if (stackContains(ACCUPARSERNight))
            data_ptr[baseListIdx].Night.WindGustSpeed = value.toFloat();

    }
    else if (STACK_HAS_SUFFIX(WindSpeed_suffix)) {
        if (stackContains(ACCUPARSERDay))
            data_ptr[baseListIdx].Day.WindSpeed = value.toFloat();
        else if (stackContains(ACCUPARSERNight))
            data_ptr[baseListIdx].Night.WindSpeed = value.toFloat();

    }
    else if (STACK_HAS_SUFFIX(WindDirection_suffix)) {
        if (stackContains(ACCUPARSERDay))
            data_ptr[baseListIdx].Day.WindDirection = value.toInt();
        else if (stackContains(ACCUPARSERNight))
            data_ptr[baseListIdx].Night.WindDirection = value.toInt();

    }
    else if (STACK_HAS_SUFFIX(CloudCover_suffix)) {
        if (stackContains(ACCUPARSERDay))
            data_ptr[baseListIdx].Day.CloudCover = value.toInt();
        else if (stackContains(ACCUPARSERNight))
            data_ptr[baseListIdx].Night.CloudCover = value.toInt();

    }
    else if (STACK_HAS_SUFFIX(IceProbability_suffix)) {
        if (stackContains(ACCUPARSERDay))
            data_ptr[baseListIdx].Day.IceProbability = value.toInt();
        else if (stackContains(ACCUPARSERNight))
            data_ptr[baseListIdx].Night.IceProbability = value.toInt();

    }
    else if (STACK_HAS_SUFFIX(PrecipitationProbability_suffix)) {
        if (stackContains(ACCUPARSERDay))
            data_ptr[baseListIdx].Day.PrecipitationProbability = value.toInt();
        else if (stackContains(ACCUPARSERNight))
            data_ptr[baseListIdx].Night.PrecipitationProbability = value.toInt();

    }
    else if (STACK_HAS_SUFFIX(RainProbability_suffix)) {
        if (stackContains(ACCUPARSERDay))
            data_ptr[baseListIdx].Day.RainProbability = value.toInt();
        else if (stackContains(ACCUPARSERNight))
            data_ptr[baseListIdx].Night.RainProbability = value.toInt();

    }
    else if (STACK_HAS_SUFFIX(SnowProbability_suffix)) {
        if (stackContains(ACCUPARSERDay))
            data_ptr[baseListIdx].Day.SnowProbability = value.toInt();
        else if (stackContains(ACCUPARSERNight))
            data_ptr[baseListIdx].Night.SnowProbability = value.toInt();

    }
    else if (STACK_HAS_SUFFIX(ThunderstormProbability_suffix)) {
        if (stackContains(ACCUPARSERDay))
            data_ptr[baseListIdx].Day.ThunderstormProbability = value.toInt();
        else if (stackContains(ACCUPARSERNight))
            data_ptr[baseListIdx].Night.ThunderstormProbability = value.toInt();

    }
    else if (STACK_HAS_SUFFIX(Icon_suffix)) {
        if (stackContains(ACCUPARSERDay))
            data_ptr[baseListIdx].Day.WeatherIcon = value.toInt();
        else if (stackContains(ACCUPARSERNight))
            data_ptr[baseListIdx].Night.WeatherIcon = value.toInt();

    }

    popAllKeys();
}

/*
 *  Data retrieval over HTTP
 */
static const char currentURLTemplate[] PROGMEM = "http://dataservice.accuweather.com/currentconditions/v1/%d?apikey=%s&details=true&language=%s";
int Accuweather::getCurrent(AccuweatherCurrentData* data_ptr) {
    char url[256];
    snprintf_P(url, 256, currentURLTemplate, locationID, apiKey, languageID);
    WiFiClient client;
    http.begin(client, url);
    int httpCode = http.GET();
    if (httpCode > 0) {
      if (httpCode == HTTP_CODE_OK) {
            length = http.getSize();
            parser.reset();
            listener = new AccuweatherCurrentParser(data_ptr, isMetric);
            parser.setListener(listener);
            return 0;
        }
    }
    //If we got here, we failed to get data
    http.end();
    return httpCode;
}

static const char hourlyURLTemplate[] PROGMEM = "http://dataservice.accuweather.com/forecasts/v1/hourly/%dhour/%d?apikey=%s&details=true&metric=%s&language=%s";
int Accuweather::getHourly(AccuweatherHourlyData* data_ptr, int hours){
    static const int possibleHours[] = {120, 72, 24, 12, 1};
    int hoursToGet = possibleHours[0];
    for (int i = 0; i < SIZE_OF_CONST_TABLE(possibleHours); i++){
        if (hours <= possibleHours[i]){
            hoursToGet = possibleHours[i];
        }
        else {
            break;
        }
    }

    char url[256];
    snprintf_P(url, 256, hourlyURLTemplate, hoursToGet, locationID, apiKey, (isMetric ? "true" : "false"), languageID);
    WiFiClient client;
    http.begin(client, url);

    int httpCode = http.GET();
    if (httpCode > 0) {
      if (httpCode == HTTP_CODE_OK) {
            length = http.getSize();
            parser.reset();
            listener = new AccuweatherHourlyParser(data_ptr, hours);
            parser.setListener(listener);
            return 0;
        }
    }
    //If we got here, we failed to get data
    http.end();
    return httpCode;
}

static const char dailyURLTemplate[] PROGMEM = "http://dataservice.accuweather.com/forecasts/v1/daily/%dday/%d?apikey=%s&details=true&metric=%s&language=%s";
int Accuweather::getDaily(AccuweatherDailyData* data_ptr, int days){
    static const int possibleDays[] = {15, 10, 5, 1};
    int daysToGet = possibleDays[0];
    for (int i = 0; i < SIZE_OF_CONST_TABLE(possibleDays); i++){
        if (days <= possibleDays[i]){
            daysToGet = possibleDays[i];
        }
        else {
            break;
        }
    }

    char url[256];
    snprintf_P(url, 256, dailyURLTemplate, daysToGet, locationID, apiKey, (isMetric ? "true" : "false"), languageID);
    WiFiClient client;
    http.begin(client, url);

    int httpCode = http.GET();
    if (httpCode > 0) {
      if (httpCode == HTTP_CODE_OK) {
            length = http.getSize();
            parser.reset();
            listener = new AccuweatherDailyParser(data_ptr, days);
            parser.setListener(listener);
            return 0;
        }
    }
    //If we got here, we failed to get data
    http.end();
    return httpCode;
}

void Accuweather::freeConnection(){
    http.end();
    delete listener;
}

/*
 *  continueDownload() function downloads data in 128 byte chunks.
 *  Returns <0 on download error, 0 on download finished, >0 if the download can be continued.
 *  This function should be called repeatedly until the returned value is 0.
 *  The function will close the connection and free resources automatically.
 */
int Accuweather::continueDownload(){
    // read all data from server
    if (http.connected() && (length > 0 || length == -1)){
        // create buffer for read
        uint8_t buff[128] = { 0 };

        // get tcp stream
        WiFiClient * stream = http.getStreamPtr();

        // get available data size
        size_t size = stream->available();
        int c = size;
        if (size) {
            // read up to 128 byte
            c = stream->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size));
            
            for (int i = 0; i < c; i++){
                parser.parse(buff[i]);
            }
            if (length > 0) {
                length -= c;
            }
        }
        return c+1;
    }
    else if (length == 0){
        freeConnection();
        return 0;
    }
    else {
        return -1;
    }
}

Thank you so much @johnwasser
It works perfectly

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.