Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
NWSWeather.cpp
- Committer:
- WiredHome
- Date:
- 2014-04-20
- Revision:
- 4:94dfdc405640
- Parent:
- 2:eae60b64066e
- Child:
- 6:cf96f2787a4e
File content as of revision 4:94dfdc405640:
// // This file contains the interface for gathering forecast from NWS. // // attention: This program is copyright (c) 2014 by Smartware Computing, all // rights reserved. // // This software, and/or material is the property of Smartware Computing. All // use, disclosure, and/or reproduction not specifically authorized by Smartware // Computing is prohibited. // // This software may be freely used for non-commercial purposes, and any // derivative work shall carry the original copyright. The author of // a derivative work shall make clear that it is a derivative work. // // author David Smart, Smartware Computing // #include "NWSWeather.h" //#define DEBUG "NWS " // ... // INFO("Stuff to show %d", var); // new-line is automatically appended // #if (defined(DEBUG) && !defined(TARGET_LPC11U24)) #define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); #define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); #define ERR(x, ...) std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); #else #define INFO(x, ...) #define WARN(x, ...) #define ERR(x, ...) #endif static NWSWeather::XMLItem_T WeatherData[] = { {"observation_time_rfc822", NWSWeather::isString}, {"suggested_pickup", NWSWeather::isString}, {"suggested_pickup_period", NWSWeather::isInt}, {"location", NWSWeather::isString}, {"weather", NWSWeather::isString}, {"temp_f", NWSWeather::isFloat}, {"temp_c", NWSWeather::isFloat}, {"relative_humidity", NWSWeather::isInt}, {"wind_degrees", NWSWeather::isInt}, {"wind_mph", NWSWeather::isFloat}, {"pressure_mb", NWSWeather::isFloat}, {"pressure_in", NWSWeather::isFloat}, {"dewpoint_f", NWSWeather::isFloat}, {"dewpoint_c", NWSWeather::isFloat}, {"windchill_f", NWSWeather::isFloat}, {"windchill_c", NWSWeather::isFloat}, {"visibility_mi", NWSWeather::isFloat}, {"icon_url_base", NWSWeather::isString}, {"icon_url_name", NWSWeather::isString}, {"latitude", NWSWeather::isFloat}, {"longitude", NWSWeather::isFloat}, }; #define MAXPARAMLEN 23 #define WeatherItemCount (sizeof(WeatherData)/sizeof(WeatherData[0])) NWSWeather::NWSWeather(const char * baseURL) { setAlternateURL(baseURL); } NWSWeather::~NWSWeather() { ClearWeatherRecords(); } NWSWeather::NWSReturnCode_T NWSWeather::setAlternateURL(const char * baseURL) { if (m_baseurl) free(m_baseurl); m_baseurl = (char *)malloc(strlen(baseURL)+1); if (m_baseurl) strcpy(m_baseurl, baseURL); else { return nomemory; } ClearWeatherRecords(); return noerror; } uint16_t NWSWeather::count(void) { return WeatherItemCount; } NWSWeather::NWSReturnCode_T NWSWeather::get(const char * site, int responseSize) { NWSReturnCode_T retCode = nomemory; char *url = NULL; char *message = (char *)malloc(responseSize); INFO("get(%s)", site); if (!message) ERR("no memory"); while (message) { url = (char *)malloc(strlen(m_baseurl) + strlen(site) + 5); if (url) { strcpy(url, m_baseurl); strcat(url, site); strcat(url, ".xml"); INFO(" url: %s", url); http.setMaxRedirections(3); int ret = http.get(url, message, responseSize); if (!ret) { INFO("ret is %d", ret); if (http.getHTTPResponseCode() >= 300 && http.getHTTPResponseCode() < 400) { retCode = noerror; // redirection that was not satisfied. break; } else { ParseWeatherXML(message); retCode = noerror; break; } } else { WARN("get returned %d, no response?", ret); retCode = noresponse; break; } } else { ERR("no memory"); retCode = nomemory; break; } } // while(...) but configured with break for only 1 pass. INFO(" ret is %d", retCode); if (url) free(url); if (message) free(message); INFO(" mem freed."); return retCode; } NWSWeather::NWSReturnCode_T NWSWeather::isUpdated(uint16_t i) { if (i < WeatherItemCount) { if (WeatherData[i].updated) return noerror; else return noupdate; } else { return badparameter; } } NWSWeather::NWSReturnCode_T NWSWeather::isUpdated(const char * name) { if (name) { for (int i=0; i < WeatherItemCount; i++) { if (strcmp(name, WeatherData[i].name) == 0) { if (WeatherData[i].updated) return noerror; else return noupdate; } } } return badparameter; } NWSWeather::NWSReturnCode_T NWSWeather::getParam(uint16_t i, char *name, Value_T *value, TypeOf_T *typeis) { if (i < WeatherItemCount) { *name = *WeatherData[i].name; *value = WeatherData[i].value; if (typeis) *typeis = WeatherData[i].typeis; return noerror; } else { return badparameter; } } NWSWeather::NWSReturnCode_T NWSWeather::getParam(const char *name, Value_T *value, TypeOf_T *typeis) { for (int i=0; i < WeatherItemCount; i++) { if (strcmp(name, WeatherData[i].name) == 0) { *value = WeatherData[i].value; if (typeis) *typeis = WeatherData[i].typeis; return noerror; } } return badparameter; } void NWSWeather::ClearWeatherRecords(void) { int i; int count = WeatherItemCount; for (i=0; i<count; i++) { switch(WeatherData[i].typeis) { case isFloat: WeatherData[i].value.fValue = 0.0; WeatherData[i].updated = false; break; case isInt: WeatherData[i].value.iValue = 0; WeatherData[i].updated = false; break; case isString: if (WeatherData[i].value.sValue) { free(WeatherData[i].value.sValue); WeatherData[i].value.sValue = NULL; } WeatherData[i].updated = false; break; default: break; } } } void NWSWeather::PrintWeatherRecord(uint16_t i) { if (i < WeatherItemCount) { switch(WeatherData[i].typeis) { case isFloat: printf("%23s = %f\r\n", WeatherData[i].name, WeatherData[i].value.fValue); break; case isInt: printf("%23s = %d\r\n", WeatherData[i].name, WeatherData[i].value.iValue); break; case isString: printf("%23s = %s\r\n", WeatherData[i].name, WeatherData[i].value.sValue); break; default: break; } } } void NWSWeather::PrintAllWeatherRecords(void) { for (int i=0; i<WeatherItemCount; i++) { PrintWeatherRecord(i); } } NWSWeather::NWSReturnCode_T NWSWeather::ParseWeatherRecord(char * p) { // <tag_name>value</tag_name> // p1 p2 p3 char *p1, *p2, *p3; int i; int count = WeatherItemCount; p1 = strchr(p, '<'); if (p1++) { p2 = strchr(p1+1, '>'); if (p2) { p3 = strchr(p2+1, '<'); if (p3) { *p2++ = '\0'; *p3 = '\0'; for (i=0; i<count; i++) { if (strcmp(p1, WeatherData[i].name) == 0) { switch(WeatherData[i].typeis) { case isFloat: WeatherData[i].value.fValue = atof(p2); WeatherData[i].updated = true; break; case isInt: WeatherData[i].value.iValue = atoi(p2); WeatherData[i].updated = true; break; case isString: if (WeatherData[i].value.sValue) free(WeatherData[i].value.sValue); WeatherData[i].value.sValue = (char *)malloc(strlen(p2)+1); if (WeatherData[i].value.sValue) { strcpy(WeatherData[i].value.sValue, p2); WeatherData[i].updated = true; } break; default: return badparameter; //break; } return noerror; } } } } } return noparamfound; } void NWSWeather::ParseWeatherXML(char * message) { char * p = message; ClearWeatherRecords(); while (*p) { char * n = strchr(p, '\n'); if (*n) { *n = '\0'; ParseWeatherRecord(p); p = n + 1; } else { ParseWeatherRecord(p); break; } } }