Update API endpoint and response handling for weather

Updated API to accommodate OpenWeatherMap updated API.
pull/168/head
Andrew Bowman 2025-11-02 21:31:49 -05:00 committed by GitHub
parent 40abdb6939
commit 7b8cc9dc34
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 308 additions and 310 deletions

View File

@ -1,311 +1,309 @@
/** The MIT License (MIT) /** The MIT License (MIT)
Copyright (c) 2018 David Payne Copyright (c) 2018 David Payne
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#include "OpenWeatherMapClient.h" #include "OpenWeatherMapClient.h"
OpenWeatherMapClient::OpenWeatherMapClient(String ApiKey, int CityIDs[], int cityCount, boolean isMetric, String language) { OpenWeatherMapClient::OpenWeatherMapClient(String ApiKey, int CityIDs[], int cityCount, boolean isMetric, String language) {
updateCityIdList(CityIDs, cityCount); updateCityIdList(CityIDs, cityCount);
updateLanguage(language); updateLanguage(language);
myApiKey = ApiKey; myApiKey = ApiKey;
setMetric(isMetric); setMetric(isMetric);
} }
void OpenWeatherMapClient::updateWeatherApiKey(String ApiKey) { void OpenWeatherMapClient::updateWeatherApiKey(String ApiKey) {
myApiKey = ApiKey; myApiKey = ApiKey;
} }
void OpenWeatherMapClient::updateLanguage(String language) { void OpenWeatherMapClient::updateLanguage(String language) {
lang = language; lang = language;
if (lang == "") { if (lang == "") {
lang = "en"; lang = "en";
} }
} }
void OpenWeatherMapClient::updateWeather() { void OpenWeatherMapClient::updateWeather() {
WiFiClient weatherClient; WiFiClient weatherClient;
String apiGetData = "GET /data/2.5/group?id=" + myCityIDs + "&units=" + units + "&cnt=1&APPID=" + myApiKey + "&lang=" + lang + " HTTP/1.1"; String apiGetData = "GET /data/2.5/weather?id=" + myCityIDs + "&units=" + units + "&cnt=1&APPID=" + myApiKey + "&lang=" + lang + " HTTP/1.1";
Serial.println("Getting Weather Data"); Serial.println("Getting Weather Data");
Serial.println(apiGetData); Serial.println(apiGetData);
result = ""; result = "";
if (weatherClient.connect(servername, 80)) { //starts client connection, checks for connection if (weatherClient.connect(servername, 80)) { //starts client connection, checks for connection
weatherClient.println(apiGetData); weatherClient.println(apiGetData);
weatherClient.println("Host: " + String(servername)); weatherClient.println("Host: " + String(servername));
weatherClient.println("User-Agent: ArduinoWiFi/1.1"); weatherClient.println("User-Agent: ArduinoWiFi/1.1");
weatherClient.println("Connection: close"); weatherClient.println("Connection: close");
weatherClient.println(); weatherClient.println();
} }
else { else {
Serial.println("connection for weather data failed"); //error message if no client connect Serial.println("connection for weather data failed"); //error message if no client connect
Serial.println(); Serial.println();
return; return;
} }
while(weatherClient.connected() && !weatherClient.available()) delay(1); //waits for data while(weatherClient.connected() && !weatherClient.available()) delay(1); //waits for data
Serial.println("Waiting for data"); Serial.println("Waiting for data");
// Check HTTP status // Check HTTP status
char status[32] = {0}; char status[32] = {0};
weatherClient.readBytesUntil('\r', status, sizeof(status)); weatherClient.readBytesUntil('\r', status, sizeof(status));
Serial.println("Response Header: " + String(status)); Serial.println("Response Header: " + String(status));
if (strcmp(status, "HTTP/1.1 200 OK") != 0) { if (strcmp(status, "HTTP/1.1 200 OK") != 0) {
Serial.print(F("Unexpected response: ")); Serial.print(F("Unexpected response: "));
Serial.println(status); Serial.println(status);
return; return;
} }
// Skip HTTP headers // Skip HTTP headers
char endOfHeaders[] = "\r\n\r\n"; char endOfHeaders[] = "\r\n\r\n";
if (!weatherClient.find(endOfHeaders)) { if (!weatherClient.find(endOfHeaders)) {
Serial.println(F("Invalid response")); Serial.println(F("Invalid response"));
return; return;
} }
const size_t bufferSize = 710; const size_t bufferSize = 710;
DynamicJsonBuffer jsonBuffer(bufferSize); DynamicJsonBuffer jsonBuffer(bufferSize);
weathers[0].cached = false; weathers[0].cached = false;
weathers[0].error = ""; weathers[0].error = "";
// Parse JSON object // Parse JSON object
JsonObject& root = jsonBuffer.parseObject(weatherClient); JsonObject& root = jsonBuffer.parseObject(weatherClient);
if (!root.success()) { if (!root.success()) {
Serial.println(F("Weather Data Parsing failed!")); Serial.println(F("Weather Data Parsing failed!"));
weathers[0].error = "Weather Data Parsing failed!"; weathers[0].error = "Weather Data Parsing failed!";
return; return;
} }
weatherClient.stop(); //stop client weatherClient.stop(); //stop client
if (root.measureLength() <= 150) { if (root.measureLength() <= 150) {
Serial.println("Error Does not look like we got the data. Size: " + String(root.measureLength())); Serial.println("Error Does not look like we got the data. Size: " + String(root.measureLength()));
weathers[0].cached = true; weathers[0].cached = true;
weathers[0].error = (const char*)root["message"]; weathers[0].error = (const char*)root["message"];
Serial.println("Error: " + weathers[0].error); Serial.println("Error: " + weathers[0].error);
return; return;
} }
int count = root["cnt"]; int count = root["cnt"];
for (int inx = 0; inx < count; inx++) { weathers[0].lat = (const char*)root["coord"]["lat"];
weathers[inx].lat = (const char*)root["list"][inx]["coord"]["lat"]; weathers[0].lon = (const char*)root["coord"]["lon"];
weathers[inx].lon = (const char*)root["list"][inx]["coord"]["lon"]; weathers[0].dt = (const char*)root["dt"];
weathers[inx].dt = (const char*)root["list"][inx]["dt"]; weathers[0].city = (const char*)root["name"];
weathers[inx].city = (const char*)root["list"][inx]["name"]; weathers[0].country = (const char*)root["sys"]["country"];
weathers[inx].country = (const char*)root["list"][inx]["sys"]["country"]; weathers[0].temp = (const char*)root["main"]["temp"];
weathers[inx].temp = (const char*)root["list"][inx]["main"]["temp"]; weathers[0].humidity = (const char*)root["main"]["humidity"];
weathers[inx].humidity = (const char*)root["list"][inx]["main"]["humidity"]; weathers[0].condition = (const char*)root["weather"][0]["main"];
weathers[inx].condition = (const char*)root["list"][inx]["weather"][0]["main"]; weathers[0].wind = (const char*)root["wind"]["speed"];
weathers[inx].wind = (const char*)root["list"][inx]["wind"]["speed"]; weathers[0].weatherId = (const char*)root["weather"][0]["id"];
weathers[inx].weatherId = (const char*)root["list"][inx]["weather"][0]["id"]; weathers[0].description = (const char*)root["weather"][0]["description"];
weathers[inx].description = (const char*)root["list"][inx]["weather"][0]["description"]; weathers[0].icon = (const char*)root["weather"][0]["icon"];
weathers[inx].icon = (const char*)root["list"][inx]["weather"][0]["icon"];
Serial.println("lat: " + weathers[inx].lat); Serial.println("lat: " + weathers[0].lat);
Serial.println("lon: " + weathers[inx].lon); Serial.println("lon: " + weathers[0].lon);
Serial.println("dt: " + weathers[inx].dt); Serial.println("dt: " + weathers[0].dt);
Serial.println("city: " + weathers[inx].city); Serial.println("city: " + weathers[0].city);
Serial.println("country: " + weathers[inx].country); Serial.println("country: " + weathers[0].country);
Serial.println("temp: " + weathers[inx].temp); Serial.println("temp: " + weathers[0].temp);
Serial.println("humidity: " + weathers[inx].humidity); Serial.println("humidity: " + weathers[0].humidity);
Serial.println("condition: " + weathers[inx].condition); Serial.println("condition: " + weathers[0].condition);
Serial.println("wind: " + weathers[inx].wind); Serial.println("wind: " + weathers[0].wind);
Serial.println("weatherId: " + weathers[inx].weatherId); Serial.println("weatherId: " + weathers[0].weatherId);
Serial.println("description: " + weathers[inx].description); Serial.println("description: " + weathers[0].description);
Serial.println("icon: " + weathers[inx].icon); Serial.println("icon: " + weathers[0].icon);
Serial.println(); Serial.println();
}
}
} String OpenWeatherMapClient::roundValue(String value) {
float f = value.toFloat();
String OpenWeatherMapClient::roundValue(String value) { int rounded = (int)(f+0.5f);
float f = value.toFloat(); return String(rounded);
int rounded = (int)(f+0.5f); }
return String(rounded);
} void OpenWeatherMapClient::updateCityIdList(int CityIDs[], int cityCount) {
myCityIDs = "";
void OpenWeatherMapClient::updateCityIdList(int CityIDs[], int cityCount) { for (int inx = 0; inx < cityCount; inx++) {
myCityIDs = ""; if (CityIDs[inx] > 0) {
for (int inx = 0; inx < cityCount; inx++) { if (myCityIDs != "") {
if (CityIDs[inx] > 0) { myCityIDs = myCityIDs + ",";
if (myCityIDs != "") { }
myCityIDs = myCityIDs + ","; myCityIDs = myCityIDs + String(CityIDs[inx]);
} }
myCityIDs = myCityIDs + String(CityIDs[inx]); }
} }
}
} void OpenWeatherMapClient::setMetric(boolean isMetric) {
if (isMetric) {
void OpenWeatherMapClient::setMetric(boolean isMetric) { units = "metric";
if (isMetric) { } else {
units = "metric"; units = "imperial";
} else { }
units = "imperial"; }
}
} String OpenWeatherMapClient::getWeatherResults() {
return result;
String OpenWeatherMapClient::getWeatherResults() { }
return result;
} String OpenWeatherMapClient::getLat(int index) {
return weathers[index].lat;
String OpenWeatherMapClient::getLat(int index) { }
return weathers[index].lat;
} String OpenWeatherMapClient::getLon(int index) {
return weathers[index].lon;
String OpenWeatherMapClient::getLon(int index) { }
return weathers[index].lon;
} String OpenWeatherMapClient::getDt(int index) {
return weathers[index].dt;
String OpenWeatherMapClient::getDt(int index) { }
return weathers[index].dt;
} String OpenWeatherMapClient::getCity(int index) {
return weathers[index].city;
String OpenWeatherMapClient::getCity(int index) { }
return weathers[index].city;
} String OpenWeatherMapClient::getCountry(int index) {
return weathers[index].country;
String OpenWeatherMapClient::getCountry(int index) { }
return weathers[index].country;
} String OpenWeatherMapClient::getTemp(int index) {
return weathers[index].temp;
String OpenWeatherMapClient::getTemp(int index) { }
return weathers[index].temp;
} String OpenWeatherMapClient::getTempRounded(int index) {
return roundValue(getTemp(index));
String OpenWeatherMapClient::getTempRounded(int index) { }
return roundValue(getTemp(index));
} String OpenWeatherMapClient::getHumidity(int index) {
return weathers[index].humidity;
String OpenWeatherMapClient::getHumidity(int index) { }
return weathers[index].humidity;
} String OpenWeatherMapClient::getHumidityRounded(int index) {
return roundValue(getHumidity(index));
String OpenWeatherMapClient::getHumidityRounded(int index) { }
return roundValue(getHumidity(index));
} String OpenWeatherMapClient::getCondition(int index) {
return weathers[index].condition;
String OpenWeatherMapClient::getCondition(int index) { }
return weathers[index].condition;
} String OpenWeatherMapClient::getWind(int index) {
return weathers[index].wind;
String OpenWeatherMapClient::getWind(int index) { }
return weathers[index].wind;
} String OpenWeatherMapClient::getWindRounded(int index) {
return roundValue(getWind(index));
String OpenWeatherMapClient::getWindRounded(int index) { }
return roundValue(getWind(index));
} String OpenWeatherMapClient::getWeatherId(int index) {
return weathers[index].weatherId;
String OpenWeatherMapClient::getWeatherId(int index) { }
return weathers[index].weatherId;
} String OpenWeatherMapClient::getDescription(int index) {
return weathers[index].description;
String OpenWeatherMapClient::getDescription(int index) { }
return weathers[index].description;
} String OpenWeatherMapClient::getIcon(int index) {
return weathers[index].icon;
String OpenWeatherMapClient::getIcon(int index) { }
return weathers[index].icon;
} boolean OpenWeatherMapClient::getCached() {
return weathers[0].cached;
boolean OpenWeatherMapClient::getCached() { }
return weathers[0].cached;
} String OpenWeatherMapClient::getMyCityIDs() {
return myCityIDs;
String OpenWeatherMapClient::getMyCityIDs() { }
return myCityIDs;
} String OpenWeatherMapClient::getError() {
return weathers[0].error;
String OpenWeatherMapClient::getError() { }
return weathers[0].error;
} String OpenWeatherMapClient::getWeatherIcon(int index)
{
String OpenWeatherMapClient::getWeatherIcon(int index) int id = getWeatherId(index).toInt();
{ String W = ")";
int id = getWeatherId(index).toInt(); switch(id)
String W = ")"; {
switch(id) case 800: W = "B"; break;
{ case 801: W = "Y"; break;
case 800: W = "B"; break; case 802: W = "H"; break;
case 801: W = "Y"; break; case 803: W = "H"; break;
case 802: W = "H"; break; case 804: W = "Y"; break;
case 803: W = "H"; break;
case 804: W = "Y"; break; case 200: W = "0"; break;
case 201: W = "0"; break;
case 200: W = "0"; break; case 202: W = "0"; break;
case 201: W = "0"; break; case 210: W = "0"; break;
case 202: W = "0"; break; case 211: W = "0"; break;
case 210: W = "0"; break; case 212: W = "0"; break;
case 211: W = "0"; break; case 221: W = "0"; break;
case 212: W = "0"; break; case 230: W = "0"; break;
case 221: W = "0"; break; case 231: W = "0"; break;
case 230: W = "0"; break; case 232: W = "0"; break;
case 231: W = "0"; break;
case 232: W = "0"; break; case 300: W = "R"; break;
case 301: W = "R"; break;
case 300: W = "R"; break; case 302: W = "R"; break;
case 301: W = "R"; break; case 310: W = "R"; break;
case 302: W = "R"; break; case 311: W = "R"; break;
case 310: W = "R"; break; case 312: W = "R"; break;
case 311: W = "R"; break; case 313: W = "R"; break;
case 312: W = "R"; break; case 314: W = "R"; break;
case 313: W = "R"; break; case 321: W = "R"; break;
case 314: W = "R"; break;
case 321: W = "R"; break; case 500: W = "R"; break;
case 501: W = "R"; break;
case 500: W = "R"; break; case 502: W = "R"; break;
case 501: W = "R"; break; case 503: W = "R"; break;
case 502: W = "R"; break; case 504: W = "R"; break;
case 503: W = "R"; break; case 511: W = "R"; break;
case 504: W = "R"; break; case 520: W = "R"; break;
case 511: W = "R"; break; case 521: W = "R"; break;
case 520: W = "R"; break; case 522: W = "R"; break;
case 521: W = "R"; break; case 531: W = "R"; break;
case 522: W = "R"; break;
case 531: W = "R"; break; case 600: W = "W"; break;
case 601: W = "W"; break;
case 600: W = "W"; break; case 602: W = "W"; break;
case 601: W = "W"; break; case 611: W = "W"; break;
case 602: W = "W"; break; case 612: W = "W"; break;
case 611: W = "W"; break; case 615: W = "W"; break;
case 612: W = "W"; break; case 616: W = "W"; break;
case 615: W = "W"; break; case 620: W = "W"; break;
case 616: W = "W"; break; case 621: W = "W"; break;
case 620: W = "W"; break; case 622: W = "W"; break;
case 621: W = "W"; break;
case 622: W = "W"; break; case 701: W = "M"; break;
case 711: W = "M"; break;
case 701: W = "M"; break; case 721: W = "M"; break;
case 711: W = "M"; break; case 731: W = "M"; break;
case 721: W = "M"; break; case 741: W = "M"; break;
case 731: W = "M"; break; case 751: W = "M"; break;
case 741: W = "M"; break; case 761: W = "M"; break;
case 751: W = "M"; break; case 762: W = "M"; break;
case 761: W = "M"; break; case 771: W = "M"; break;
case 762: W = "M"; break; case 781: W = "M"; break;
case 771: W = "M"; break;
case 781: W = "M"; break; default:break;
}
default:break; return W;
}
return W;
} }