You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

188 lines
13 KiB

void readWeather()
{
byte Attempts = 1;
bool RxWeather = false;
bool RxForecast = false;
WiFiClient client; // wifi client object
while ((RxWeather == false || RxForecast == false) && Attempts <= 2) { // Try up-to 2 time for Weather and Forecast data
if (RxWeather == false) RxWeather = obtainWeatherData(client, "weather");
if (RxForecast == false) RxForecast = obtainWeatherData(client, "forecast");
Attempts++;
}
Serial.println("Received all weather data...");
}
//#########################################################################################
bool obtainWeatherData(WiFiClient & client, const String & RequestType) {
const String units = (Units == "M" ? "metric" : "imperial");
client.stop(); // close connection before sending a new request
HTTPClient http;
// String uri = "/data/2.5/" + RequestType + "/daily?q=" + City + "," + Country + "&APPID=" + apikey + "&mode=json&units=" + units + "&lang=" + Language;
String uri = "/data/2.5/" + RequestType + "?q=" + City + "," + Country + "&APPID=" + apikey + "&mode=json&units=" + units + "&lang=" + Language;
if (RequestType != "weather")
{
if(forcast==0)
{ uri = "/data/2.5/" + RequestType + "/daily?q=" + City + "," + Country + "&APPID=" + apikey + "&mode=json&units=" + units + "&lang=" + Language;
uri += "&cnt=" + String(max_readings);
}
else
{
uri = "/data/2.5/" + RequestType + "?q=" + City + "," + Country + "&APPID=" + apikey + "&mode=json&units=" + units;
uri += "&cnt=" + String(max_readings1);
// data/2.5/forecast?q=Yevpatoriya,UA&APPID=a0b9f94d153cbcbfeb00ea5632db24ac&mode=json&units=metric&cnt=24
}
}
Serial.println(uri);
http.begin(client, server, 80, uri); //http.begin(uri,test_root_ca); //HTTPS example connection
int httpCode = http.GET();
if (httpCode == HTTP_CODE_OK) {
// Serial.println("HTTP_CODE_OK");
if (!DecodeWeather(http.getStream(), RequestType)) return false;
client.stop();
http.end();
return true;
}
else
{
Serial.printf("connection failed, error: %s", http.errorToString(httpCode).c_str());
Serial.println(" ");
client.stop();
http.end();
return false;
}
http.end();
return true;
}
//************************************************************************************************************
bool DecodeWeather(WiFiClient& json, String Type) {
Serial.print(F("\nCreating object...and "));
DynamicJsonDocument doc(64 * 1024); // allocate the JsonDocument
DeserializationError error = deserializeJson(doc, json); // Deserialize the JSON document
if (error) { // Test if parsing succeeds.
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.c_str());
return false;
}
// convert it to a JsonObject
JsonObject root = doc.as<JsonObject>();
Serial.println(" Decoding " + Type + " data");
if (Type == "weather") {
// All Serial.println statements are for diagnostic purposes and some are not required, remove if not needed with //
//WxConditions[0].lon = root["coord"]["lon"].as<float>(); Serial.println(" Lon: " + String(WxConditions[0].lon));
//WxConditions[0].lat = root["coord"]["lat"].as<float>(); Serial.println(" Lat: " + String(WxConditions[0].lat));
WxConditions[0].Main0 = root["weather"][0]["main"].as<char*>(); Serial.println("Main: " + String(WxConditions[0].Main0));
WxConditions[0].Forecast0 = root["weather"][0]["description"].as<char*>(); Serial.println("For0: " + String(WxConditions[0].Forecast0));
//WxConditions[0].Forecast1 = root["weather"][1]["description"].as<char*>(); Serial.println("For1: " + String(WxConditions[0].Forecast1));
//WxConditions[0].Forecast2 = root["weather"][2]["description"].as<char*>(); Serial.println("For2: " + String(WxConditions[0].Forecast2));
WxConditions[0].Icon = root["weather"][0]["icon"].as<char*>(); Serial.println("Icon: " + String(WxConditions[0].Icon));
WxConditions[0].Temperature = root["main"]["temp"].as<float>(); Serial.println("Temp: " + String(WxConditions[0].Temperature));
WxConditions[0].Pressure = root["main"]["pressure"].as<float>(); Serial.println("Pres: " + String(WxConditions[0].Pressure));
WxConditions[0].Humidity = root["main"]["humidity"].as<float>(); Serial.println("Humi: " + String(WxConditions[0].Humidity));
WxConditions[0].Low = root["main"]["temp_min"].as<float>(); Serial.println("TLow: " + String(WxConditions[0].Low));
WxConditions[0].High = root["main"]["temp_max"].as<float>(); Serial.println("THig: " + String(WxConditions[0].High));
WxConditions[0].Windspeed = root["wind"]["speed"].as<float>(); Serial.println("WSpd: " + String(WxConditions[0].Windspeed));
WxConditions[0].Winddir = root["wind"]["deg"].as<float>(); Serial.println("WDir: " + String(WxConditions[0].Winddir));
WxConditions[0].Cloudcover = root["clouds"]["all"].as<int>(); Serial.println("CCov: " + String(WxConditions[0].Cloudcover)); // in % of cloud cover
WxConditions[0].Visibility = root["visibility"].as<int>(); Serial.println("Visi: " + String(WxConditions[0].Visibility)); // in metres
WxConditions[0].Rainfall = root["rain"]["1h"].as<float>(); Serial.println("Rain: " + String(WxConditions[0].Rainfall));
WxConditions[0].Snowfall = root["snow"]["1h"].as<float>(); Serial.println("Snow: " + String(WxConditions[0].Snowfall));
//WxConditions[0].Country = root["sys"]["country"].as<char*>(); Serial.println("Ctry: " + String(WxConditions[0].Country));
WxConditions[0].Sunrise = root["sys"]["sunrise"].as<int>(); Serial.println("SRis: " + String(WxConditions[0].Sunrise));
WxConditions[0].Sunset = root["sys"]["sunset"].as<int>(); Serial.println("SSet: " + String(WxConditions[0].Sunset));
WxConditions[0].Timezone = root["timezone"].as<int>(); Serial.println("TZon: " + String(WxConditions[0].Timezone));
}
if (Type == "forecast") {
//Serial.println(json);
if(forcast==0)
{ Serial.print(F("\nReceiving Forecast period - ")); //------------------------------------------------
JsonArray list = root["list"];
for (byte r = 0; r < max_readings; r++) {
Serial.println("\nPeriod-" + String(r) + "--------------");
WxForecast[r].Dt = list[r]["dt"].as<int>();
// WxForecast[r].Temperature = list[r]["main"]["temp"].as<float>(); Serial.println("Temp: " + String(WxForecast[r].Temperature));
WxForecast[r].day = list[r]["temp"]["day"].as<float>(); Serial.println("Tday: " + String(WxForecast[r].day));
WxForecast[r].night = list[r]["temp"]["night"].as<float>(); Serial.println("Tnight: " + String(WxForecast[r].night));
WxForecast[r].Pressure = list[r]["pressure"].as<float>(); Serial.println("Pres: " + String(WxForecast[r].Pressure));
WxForecast[r].Humidity = list[r]["humidity"].as<float>(); Serial.println("Humi: " + String(WxForecast[r].Humidity));
//WxForecast[r].Forecast0 = list[r]["weather"][0]["main"].as<char*>(); Serial.println("For0: " + String(WxForecast[r].Forecast0));
//WxForecast[r].Forecast1 = list[r]["weather"][1]["main"].as<char*>(); Serial.println("For1: " + String(WxForecast[r].Forecast1));
//WxForecast[r].Forecast2 = list[r]["weather"][2]["main"].as<char*>(); Serial.println("For2: " + String(WxForecast[r].Forecast2));
WxForecast[r].Icon = list[r]["weather"][0]["icon"].as<char*>(); Serial.println("Icon: " + String(WxForecast[r].Icon));
//WxForecast[r].Description = list[r]["weather"][0]["description"].as<char*>(); Serial.println("Desc: " + String(WxForecast[r].Description));
WxForecast[r].Cloudcover = list[r]["clouds"].as<int>(); Serial.println("CCov: " + String(WxForecast[r].Cloudcover)); // in % of cloud cover
WxForecast[r].Windspeed = list[r]["speed"].as<float>(); Serial.println("WSpd: " + String(WxForecast[r].Windspeed));
WxForecast[r].Winddir = list[r]["deg"].as<float>(); Serial.println("WDir: " + String(WxForecast[r].Winddir));
// WxForecast[r].Rainfall = list[r]["rain"]["3h"].as<float>(); Serial.println("Rain: " + String(WxForecast[r].Rainfall));
// WxForecast[r].Snowfall = list[r]["snow"]["3h"].as<float>(); Serial.println("Snow: " + String(WxForecast[r].Snowfall));
// WxForecast[r].Period = list[r]["dt_txt"].as<char*>(); Serial.println("Peri: " + String(WxForecast[r].Period));
}
//------------------------------------------
float pressure_trend = WxForecast[0].Pressure - WxForecast[2].Pressure; // Measure pressure slope between ~now and later
pressure_trend = ((int)(pressure_trend * 10)) / 10.0; // Remove any small variations less than 0.1
WxConditions[0].Trend = "=";
if (pressure_trend > 0) WxConditions[0].Trend = "+";
if (pressure_trend < 0) WxConditions[0].Trend = "-";
if (pressure_trend == 0) WxConditions[0].Trend = "0";
if (Units == "I") Convert_Readings_to_Imperial();
}
else
{
//Serial.println(json);
Serial.print(F("\nReceiving Forecast period - ")); //------------------------------------------------
JsonArray list = root["list"];
for (byte r = 0; r < max_readings1; r++) {
Serial.println("\nPeriod-" + String(r) + "--------------");
WxForecast[r].Dt = list[r]["dt"].as<int>();
WxForecast[r].Temperature = list[r]["main"]["temp"].as<float>(); Serial.println("Temp: " + String(WxForecast[r].Temperature));
WxForecast[r].Low = list[r]["main"]["temp_min"].as<float>(); Serial.println("TLow: " + String(WxForecast[r].Low));
WxForecast[r].High = list[r]["main"]["temp_max"].as<float>(); Serial.println("THig: " + String(WxForecast[r].High));
WxForecast[r].Pressure = list[r]["main"]["pressure"].as<float>(); Serial.println("Pres: " + String(WxForecast[r].Pressure));
WxForecast[r].Humidity = list[r]["main"]["humidity"].as<float>(); Serial.println("Humi: " + String(WxForecast[r].Humidity));
//WxForecast[r].Forecast0 = list[r]["weather"][0]["main"].as<char*>(); Serial.println("For0: " + String(WxForecast[r].Forecast0));
//WxForecast[r].Forecast1 = list[r]["weather"][1]["main"].as<char*>(); Serial.println("For1: " + String(WxForecast[r].Forecast1));
//WxForecast[r].Forecast2 = list[r]["weather"][2]["main"].as<char*>(); Serial.println("For2: " + String(WxForecast[r].Forecast2));
WxForecast[r].Icon = list[r]["weather"][0]["icon"].as<char*>(); Serial.println("Icon: " + String(WxForecast[r].Icon));
//WxForecast[r].Description = list[r]["weather"][0]["description"].as<char*>(); Serial.println("Desc: " + String(WxForecast[r].Description));
//WxForecast[r].Cloudcover = list[r]["clouds"]["all"].as<int>(); Serial.println("CCov: " + String(WxForecast[r].Cloudcover)); // in % of cloud cover
//WxForecast[r].Windspeed = list[r]["wind"]["speed"].as<float>(); Serial.println("WSpd: " + String(WxForecast[r].Windspeed));
//WxForecast[r].Winddir = list[r]["wind"]["deg"].as<float>(); Serial.println("WDir: " + String(WxForecast[r].Winddir));
WxForecast[r].Rainfall = list[r]["rain"]["3h"].as<float>(); Serial.println("Rain: " + String(WxForecast[r].Rainfall));
WxForecast[r].Snowfall = list[r]["snow"]["3h"].as<float>(); Serial.println("Snow: " + String(WxForecast[r].Snowfall));
WxForecast[r].Period = list[r]["dt_txt"].as<char*>(); Serial.println("Peri: " + String(WxForecast[r].Period));
}
//------------------------------------------
float pressure_trend = WxForecast[0].Pressure - WxForecast[2].Pressure; // Measure pressure slope between ~now and later
pressure_trend = ((int)(pressure_trend * 10)) / 10.0; // Remove any small variations less than 0.1
WxConditions[0].Trend = "=";
if (pressure_trend > 0) WxConditions[0].Trend = "+";
if (pressure_trend < 0) WxConditions[0].Trend = "-";
if (pressure_trend == 0) WxConditions[0].Trend = "0";
if (Units == "I") Convert_Readings_to_Imperial();
}
}
return true;
}
//#########################################################################################
void Convert_Readings_to_Imperial() { // Only the first 3-hours are used
WxConditions[0].Pressure = hPa_to_inHg(WxConditions[0].Pressure);
WxForecast[0].Rainfall = mm_to_inches(WxForecast[0].Rainfall);
WxForecast[0].Snowfall = mm_to_inches(WxForecast[0].Snowfall);
}
//************************************************************************************
//************************************************************************************************************
float mm_to_inches(float value_mm) {
return 0.0393701 * value_mm;
}
float hPa_to_inHg(float value_hPa) {
return 0.02953 * value_hPa;
}