David Smart / NWSWeather
Committer:
WiredHome
Date:
Mon Dec 22 17:21:50 2014 +0000
Revision:
10:548533964124
Parent:
8:8a3371926b32
Child:
11:98afc5abbfb8
Updates to align with latest mbed, Ethernet, minor documentation.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
WiredHome 2:eae60b64066e 1 //
WiredHome 2:eae60b64066e 2 // This file contains the interface for gathering forecast from NWS.
WiredHome 2:eae60b64066e 3 //
WiredHome 2:eae60b64066e 4 // attention: This program is copyright (c) 2014 by Smartware Computing, all
WiredHome 2:eae60b64066e 5 // rights reserved.
WiredHome 2:eae60b64066e 6 //
WiredHome 2:eae60b64066e 7 // This software, and/or material is the property of Smartware Computing. All
WiredHome 2:eae60b64066e 8 // use, disclosure, and/or reproduction not specifically authorized by Smartware
WiredHome 2:eae60b64066e 9 // Computing is prohibited.
WiredHome 2:eae60b64066e 10 //
WiredHome 2:eae60b64066e 11 // This software may be freely used for non-commercial purposes, and any
WiredHome 2:eae60b64066e 12 // derivative work shall carry the original copyright. The author of
WiredHome 2:eae60b64066e 13 // a derivative work shall make clear that it is a derivative work.
WiredHome 2:eae60b64066e 14 //
WiredHome 2:eae60b64066e 15 // author David Smart, Smartware Computing
WiredHome 2:eae60b64066e 16 //
WiredHome 2:eae60b64066e 17 #include "NWSWeather.h"
WiredHome 0:4435c965d95d 18
WiredHome 10:548533964124 19 #define DEBUG "NWS "
WiredHome 2:eae60b64066e 20 // ...
WiredHome 2:eae60b64066e 21 // INFO("Stuff to show %d", var); // new-line is automatically appended
WiredHome 2:eae60b64066e 22 //
WiredHome 2:eae60b64066e 23 #if (defined(DEBUG) && !defined(TARGET_LPC11U24))
WiredHome 2:eae60b64066e 24 #define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 2:eae60b64066e 25 #define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 2:eae60b64066e 26 #define ERR(x, ...) std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 2:eae60b64066e 27 #else
WiredHome 2:eae60b64066e 28 #define INFO(x, ...)
WiredHome 2:eae60b64066e 29 #define WARN(x, ...)
WiredHome 2:eae60b64066e 30 #define ERR(x, ...)
WiredHome 2:eae60b64066e 31 #endif
WiredHome 0:4435c965d95d 32
WiredHome 0:4435c965d95d 33
WiredHome 1:e077d6502c94 34 static NWSWeather::XMLItem_T WeatherData[] = {
WiredHome 1:e077d6502c94 35 {"observation_time_rfc822", NWSWeather::isString},
WiredHome 8:8a3371926b32 36 {"suggested_pickup", NWSWeather::isInt},
WiredHome 1:e077d6502c94 37 {"suggested_pickup_period", NWSWeather::isInt},
WiredHome 1:e077d6502c94 38 {"location", NWSWeather::isString},
WiredHome 1:e077d6502c94 39 {"weather", NWSWeather::isString},
WiredHome 1:e077d6502c94 40 {"temp_f", NWSWeather::isFloat},
WiredHome 1:e077d6502c94 41 {"temp_c", NWSWeather::isFloat},
WiredHome 1:e077d6502c94 42 {"relative_humidity", NWSWeather::isInt},
WiredHome 1:e077d6502c94 43 {"wind_degrees", NWSWeather::isInt},
WiredHome 1:e077d6502c94 44 {"wind_mph", NWSWeather::isFloat},
WiredHome 1:e077d6502c94 45 {"pressure_mb", NWSWeather::isFloat},
WiredHome 1:e077d6502c94 46 {"pressure_in", NWSWeather::isFloat},
WiredHome 1:e077d6502c94 47 {"dewpoint_f", NWSWeather::isFloat},
WiredHome 1:e077d6502c94 48 {"dewpoint_c", NWSWeather::isFloat},
WiredHome 1:e077d6502c94 49 {"windchill_f", NWSWeather::isFloat},
WiredHome 1:e077d6502c94 50 {"windchill_c", NWSWeather::isFloat},
WiredHome 1:e077d6502c94 51 {"visibility_mi", NWSWeather::isFloat},
WiredHome 1:e077d6502c94 52 {"icon_url_base", NWSWeather::isString},
WiredHome 1:e077d6502c94 53 {"icon_url_name", NWSWeather::isString},
WiredHome 1:e077d6502c94 54 {"latitude", NWSWeather::isFloat},
WiredHome 1:e077d6502c94 55 {"longitude", NWSWeather::isFloat},
WiredHome 0:4435c965d95d 56 };
WiredHome 0:4435c965d95d 57
WiredHome 0:4435c965d95d 58 #define MAXPARAMLEN 23
WiredHome 0:4435c965d95d 59
WiredHome 0:4435c965d95d 60 #define WeatherItemCount (sizeof(WeatherData)/sizeof(WeatherData[0]))
WiredHome 0:4435c965d95d 61
WiredHome 0:4435c965d95d 62 NWSWeather::NWSWeather(const char * baseURL)
WiredHome 0:4435c965d95d 63 {
WiredHome 0:4435c965d95d 64 setAlternateURL(baseURL);
WiredHome 0:4435c965d95d 65 }
WiredHome 0:4435c965d95d 66
WiredHome 0:4435c965d95d 67 NWSWeather::~NWSWeather()
WiredHome 0:4435c965d95d 68 {
WiredHome 0:4435c965d95d 69 ClearWeatherRecords();
WiredHome 0:4435c965d95d 70 }
WiredHome 0:4435c965d95d 71
WiredHome 1:e077d6502c94 72 NWSWeather::NWSReturnCode_T NWSWeather::setAlternateURL(const char * baseURL)
WiredHome 0:4435c965d95d 73 {
WiredHome 0:4435c965d95d 74 if (m_baseurl)
WiredHome 0:4435c965d95d 75 free(m_baseurl);
WiredHome 0:4435c965d95d 76 m_baseurl = (char *)malloc(strlen(baseURL)+1);
WiredHome 0:4435c965d95d 77 if (m_baseurl)
WiredHome 0:4435c965d95d 78 strcpy(m_baseurl, baseURL);
WiredHome 0:4435c965d95d 79 else {
WiredHome 0:4435c965d95d 80 return nomemory;
WiredHome 0:4435c965d95d 81 }
WiredHome 0:4435c965d95d 82 ClearWeatherRecords();
WiredHome 0:4435c965d95d 83 return noerror;
WiredHome 0:4435c965d95d 84 }
WiredHome 0:4435c965d95d 85
WiredHome 0:4435c965d95d 86 uint16_t NWSWeather::count(void)
WiredHome 0:4435c965d95d 87 {
WiredHome 0:4435c965d95d 88 return WeatherItemCount;
WiredHome 0:4435c965d95d 89 }
WiredHome 0:4435c965d95d 90
WiredHome 1:e077d6502c94 91 NWSWeather::NWSReturnCode_T NWSWeather::get(const char * site, int responseSize)
WiredHome 0:4435c965d95d 92 {
WiredHome 6:cf96f2787a4e 93 HTTPClient http;
WiredHome 2:eae60b64066e 94 NWSReturnCode_T retCode = nomemory;
WiredHome 2:eae60b64066e 95 char *url = NULL;
WiredHome 0:4435c965d95d 96 char *message = (char *)malloc(responseSize);
WiredHome 0:4435c965d95d 97
WiredHome 2:eae60b64066e 98 INFO("get(%s)", site);
WiredHome 2:eae60b64066e 99 if (!message)
WiredHome 2:eae60b64066e 100 ERR("no memory");
WiredHome 2:eae60b64066e 101 while (message) {
WiredHome 2:eae60b64066e 102 url = (char *)malloc(strlen(m_baseurl) + strlen(site) + 5);
WiredHome 0:4435c965d95d 103 if (url) {
WiredHome 0:4435c965d95d 104 strcpy(url, m_baseurl);
WiredHome 0:4435c965d95d 105 strcat(url, site);
WiredHome 0:4435c965d95d 106 strcat(url, ".xml");
WiredHome 2:eae60b64066e 107 INFO(" url: %s", url);
WiredHome 0:4435c965d95d 108 http.setMaxRedirections(3);
WiredHome 0:4435c965d95d 109 int ret = http.get(url, message, responseSize);
WiredHome 0:4435c965d95d 110 if (!ret) {
WiredHome 2:eae60b64066e 111 INFO("ret is %d", ret);
WiredHome 0:4435c965d95d 112 if (http.getHTTPResponseCode() >= 300 && http.getHTTPResponseCode() < 400) {
WiredHome 2:eae60b64066e 113 retCode = noerror; // redirection that was not satisfied.
WiredHome 2:eae60b64066e 114 break;
WiredHome 0:4435c965d95d 115 } else {
WiredHome 6:cf96f2787a4e 116 INFO("wx get %d bytes.\r\n", strlen(message));
WiredHome 0:4435c965d95d 117 ParseWeatherXML(message);
WiredHome 2:eae60b64066e 118 retCode = noerror;
WiredHome 2:eae60b64066e 119 break;
WiredHome 0:4435c965d95d 120 }
WiredHome 0:4435c965d95d 121 } else {
WiredHome 2:eae60b64066e 122 WARN("get returned %d, no response?", ret);
WiredHome 2:eae60b64066e 123 retCode = noresponse;
WiredHome 2:eae60b64066e 124 break;
WiredHome 0:4435c965d95d 125 }
WiredHome 0:4435c965d95d 126 } else {
WiredHome 2:eae60b64066e 127 ERR("no memory");
WiredHome 2:eae60b64066e 128 retCode = nomemory;
WiredHome 2:eae60b64066e 129 break;
WiredHome 2:eae60b64066e 130 }
WiredHome 2:eae60b64066e 131 } // while(...) but configured with break for only 1 pass.
WiredHome 2:eae60b64066e 132 INFO(" ret is %d", retCode);
WiredHome 2:eae60b64066e 133 if (url)
WiredHome 2:eae60b64066e 134 free(url);
WiredHome 2:eae60b64066e 135 if (message)
WiredHome 2:eae60b64066e 136 free(message);
WiredHome 2:eae60b64066e 137 INFO(" mem freed.");
WiredHome 2:eae60b64066e 138 return retCode;
WiredHome 2:eae60b64066e 139 }
WiredHome 2:eae60b64066e 140
WiredHome 2:eae60b64066e 141
WiredHome 2:eae60b64066e 142 NWSWeather::NWSReturnCode_T NWSWeather::isUpdated(uint16_t i)
WiredHome 2:eae60b64066e 143 {
WiredHome 2:eae60b64066e 144 if (i < WeatherItemCount) {
WiredHome 2:eae60b64066e 145 if (WeatherData[i].updated)
WiredHome 2:eae60b64066e 146 return noerror;
WiredHome 2:eae60b64066e 147 else
WiredHome 2:eae60b64066e 148 return noupdate;
WiredHome 2:eae60b64066e 149 } else {
WiredHome 2:eae60b64066e 150 return badparameter;
WiredHome 2:eae60b64066e 151 }
WiredHome 2:eae60b64066e 152 }
WiredHome 2:eae60b64066e 153
WiredHome 2:eae60b64066e 154
WiredHome 2:eae60b64066e 155 NWSWeather::NWSReturnCode_T NWSWeather::isUpdated(const char * name)
WiredHome 2:eae60b64066e 156 {
WiredHome 2:eae60b64066e 157 if (name) {
WiredHome 2:eae60b64066e 158 for (int i=0; i < WeatherItemCount; i++) {
WiredHome 2:eae60b64066e 159 if (strcmp(name, WeatherData[i].name) == 0) {
WiredHome 2:eae60b64066e 160 if (WeatherData[i].updated)
WiredHome 2:eae60b64066e 161 return noerror;
WiredHome 2:eae60b64066e 162 else
WiredHome 2:eae60b64066e 163 return noupdate;
WiredHome 2:eae60b64066e 164 }
WiredHome 0:4435c965d95d 165 }
WiredHome 0:4435c965d95d 166 }
WiredHome 2:eae60b64066e 167 return badparameter;
WiredHome 0:4435c965d95d 168 }
WiredHome 0:4435c965d95d 169
WiredHome 0:4435c965d95d 170
WiredHome 1:e077d6502c94 171 NWSWeather::NWSReturnCode_T NWSWeather::getParam(uint16_t i, char *name, Value_T *value, TypeOf_T *typeis)
WiredHome 0:4435c965d95d 172 {
WiredHome 0:4435c965d95d 173 if (i < WeatherItemCount) {
WiredHome 0:4435c965d95d 174 *name = *WeatherData[i].name;
WiredHome 0:4435c965d95d 175 *value = WeatherData[i].value;
WiredHome 0:4435c965d95d 176 if (typeis)
WiredHome 0:4435c965d95d 177 *typeis = WeatherData[i].typeis;
WiredHome 0:4435c965d95d 178 return noerror;
WiredHome 0:4435c965d95d 179 } else {
WiredHome 0:4435c965d95d 180 return badparameter;
WiredHome 0:4435c965d95d 181 }
WiredHome 0:4435c965d95d 182 }
WiredHome 0:4435c965d95d 183
WiredHome 0:4435c965d95d 184
WiredHome 1:e077d6502c94 185 NWSWeather::NWSReturnCode_T NWSWeather::getParam(const char *name, Value_T *value, TypeOf_T *typeis)
WiredHome 0:4435c965d95d 186 {
WiredHome 2:eae60b64066e 187 for (int i=0; i < WeatherItemCount; i++) {
WiredHome 2:eae60b64066e 188 if (strcmp(name, WeatherData[i].name) == 0) {
WiredHome 2:eae60b64066e 189 *value = WeatherData[i].value;
WiredHome 2:eae60b64066e 190 if (typeis)
WiredHome 2:eae60b64066e 191 *typeis = WeatherData[i].typeis;
WiredHome 2:eae60b64066e 192 return noerror;
WiredHome 0:4435c965d95d 193 }
WiredHome 0:4435c965d95d 194 }
WiredHome 0:4435c965d95d 195 return badparameter;
WiredHome 0:4435c965d95d 196 }
WiredHome 0:4435c965d95d 197
WiredHome 0:4435c965d95d 198
WiredHome 0:4435c965d95d 199 void NWSWeather::ClearWeatherRecords(void)
WiredHome 0:4435c965d95d 200 {
WiredHome 0:4435c965d95d 201 int i;
WiredHome 0:4435c965d95d 202 int count = WeatherItemCount;
WiredHome 0:4435c965d95d 203
WiredHome 0:4435c965d95d 204 for (i=0; i<count; i++) {
WiredHome 0:4435c965d95d 205 switch(WeatherData[i].typeis) {
WiredHome 0:4435c965d95d 206 case isFloat:
WiredHome 0:4435c965d95d 207 WeatherData[i].value.fValue = 0.0;
WiredHome 0:4435c965d95d 208 WeatherData[i].updated = false;
WiredHome 0:4435c965d95d 209 break;
WiredHome 0:4435c965d95d 210 case isInt:
WiredHome 0:4435c965d95d 211 WeatherData[i].value.iValue = 0;
WiredHome 0:4435c965d95d 212 WeatherData[i].updated = false;
WiredHome 0:4435c965d95d 213 break;
WiredHome 0:4435c965d95d 214 case isString:
WiredHome 0:4435c965d95d 215 if (WeatherData[i].value.sValue) {
WiredHome 0:4435c965d95d 216 free(WeatherData[i].value.sValue);
WiredHome 0:4435c965d95d 217 WeatherData[i].value.sValue = NULL;
WiredHome 0:4435c965d95d 218 }
WiredHome 0:4435c965d95d 219 WeatherData[i].updated = false;
WiredHome 0:4435c965d95d 220 break;
WiredHome 0:4435c965d95d 221 default:
WiredHome 0:4435c965d95d 222 break;
WiredHome 0:4435c965d95d 223 }
WiredHome 0:4435c965d95d 224 }
WiredHome 0:4435c965d95d 225 }
WiredHome 0:4435c965d95d 226
WiredHome 0:4435c965d95d 227 void NWSWeather::PrintWeatherRecord(uint16_t i)
WiredHome 0:4435c965d95d 228 {
WiredHome 0:4435c965d95d 229 if (i < WeatherItemCount) {
WiredHome 0:4435c965d95d 230 switch(WeatherData[i].typeis) {
WiredHome 0:4435c965d95d 231 case isFloat:
WiredHome 0:4435c965d95d 232 printf("%23s = %f\r\n", WeatherData[i].name, WeatherData[i].value.fValue);
WiredHome 0:4435c965d95d 233 break;
WiredHome 0:4435c965d95d 234 case isInt:
WiredHome 0:4435c965d95d 235 printf("%23s = %d\r\n", WeatherData[i].name, WeatherData[i].value.iValue);
WiredHome 0:4435c965d95d 236 break;
WiredHome 0:4435c965d95d 237 case isString:
WiredHome 0:4435c965d95d 238 printf("%23s = %s\r\n", WeatherData[i].name, WeatherData[i].value.sValue);
WiredHome 0:4435c965d95d 239 break;
WiredHome 0:4435c965d95d 240 default:
WiredHome 0:4435c965d95d 241 break;
WiredHome 0:4435c965d95d 242 }
WiredHome 0:4435c965d95d 243 }
WiredHome 0:4435c965d95d 244 }
WiredHome 0:4435c965d95d 245
WiredHome 0:4435c965d95d 246 void NWSWeather::PrintAllWeatherRecords(void)
WiredHome 0:4435c965d95d 247 {
WiredHome 0:4435c965d95d 248 for (int i=0; i<WeatherItemCount; i++) {
WiredHome 0:4435c965d95d 249 PrintWeatherRecord(i);
WiredHome 0:4435c965d95d 250 }
WiredHome 0:4435c965d95d 251 }
WiredHome 0:4435c965d95d 252
WiredHome 1:e077d6502c94 253 NWSWeather::NWSReturnCode_T NWSWeather::ParseWeatherRecord(char * p)
WiredHome 0:4435c965d95d 254 {
WiredHome 0:4435c965d95d 255 // <tag_name>value</tag_name>
WiredHome 0:4435c965d95d 256 // p1 p2 p3
WiredHome 0:4435c965d95d 257 char *p1, *p2, *p3;
WiredHome 0:4435c965d95d 258 int i;
WiredHome 0:4435c965d95d 259 int count = WeatherItemCount;
WiredHome 0:4435c965d95d 260
WiredHome 0:4435c965d95d 261 p1 = strchr(p, '<');
WiredHome 0:4435c965d95d 262 if (p1++) {
WiredHome 0:4435c965d95d 263 p2 = strchr(p1+1, '>');
WiredHome 0:4435c965d95d 264 if (p2) {
WiredHome 0:4435c965d95d 265 p3 = strchr(p2+1, '<');
WiredHome 0:4435c965d95d 266 if (p3) {
WiredHome 0:4435c965d95d 267 *p2++ = '\0';
WiredHome 0:4435c965d95d 268 *p3 = '\0';
WiredHome 0:4435c965d95d 269 for (i=0; i<count; i++) {
WiredHome 0:4435c965d95d 270 if (strcmp(p1, WeatherData[i].name) == 0) {
WiredHome 0:4435c965d95d 271 switch(WeatherData[i].typeis) {
WiredHome 0:4435c965d95d 272 case isFloat:
WiredHome 0:4435c965d95d 273 WeatherData[i].value.fValue = atof(p2);
WiredHome 0:4435c965d95d 274 WeatherData[i].updated = true;
WiredHome 0:4435c965d95d 275 break;
WiredHome 0:4435c965d95d 276 case isInt:
WiredHome 0:4435c965d95d 277 WeatherData[i].value.iValue = atoi(p2);
WiredHome 0:4435c965d95d 278 WeatherData[i].updated = true;
WiredHome 0:4435c965d95d 279 break;
WiredHome 0:4435c965d95d 280 case isString:
WiredHome 0:4435c965d95d 281 if (WeatherData[i].value.sValue)
WiredHome 0:4435c965d95d 282 free(WeatherData[i].value.sValue);
WiredHome 0:4435c965d95d 283 WeatherData[i].value.sValue = (char *)malloc(strlen(p2)+1);
WiredHome 0:4435c965d95d 284 if (WeatherData[i].value.sValue) {
WiredHome 0:4435c965d95d 285 strcpy(WeatherData[i].value.sValue, p2);
WiredHome 0:4435c965d95d 286 WeatherData[i].updated = true;
WiredHome 0:4435c965d95d 287 }
WiredHome 0:4435c965d95d 288 break;
WiredHome 0:4435c965d95d 289 default:
WiredHome 0:4435c965d95d 290 return badparameter;
WiredHome 0:4435c965d95d 291 //break;
WiredHome 0:4435c965d95d 292 }
WiredHome 0:4435c965d95d 293 return noerror;
WiredHome 0:4435c965d95d 294 }
WiredHome 0:4435c965d95d 295 }
WiredHome 0:4435c965d95d 296 }
WiredHome 0:4435c965d95d 297 }
WiredHome 0:4435c965d95d 298 }
WiredHome 0:4435c965d95d 299 return noparamfound;
WiredHome 0:4435c965d95d 300 }
WiredHome 0:4435c965d95d 301
WiredHome 0:4435c965d95d 302 void NWSWeather::ParseWeatherXML(char * message)
WiredHome 0:4435c965d95d 303 {
WiredHome 0:4435c965d95d 304 char * p = message;
WiredHome 0:4435c965d95d 305
WiredHome 0:4435c965d95d 306 ClearWeatherRecords();
WiredHome 0:4435c965d95d 307 while (*p) {
WiredHome 0:4435c965d95d 308 char * n = strchr(p, '\n');
WiredHome 0:4435c965d95d 309 if (*n) {
WiredHome 0:4435c965d95d 310 *n = '\0';
WiredHome 0:4435c965d95d 311 ParseWeatherRecord(p);
WiredHome 0:4435c965d95d 312 p = n + 1;
WiredHome 0:4435c965d95d 313 } else {
WiredHome 0:4435c965d95d 314 ParseWeatherRecord(p);
WiredHome 0:4435c965d95d 315 break;
WiredHome 0:4435c965d95d 316 }
WiredHome 0:4435c965d95d 317 }
WiredHome 0:4435c965d95d 318 }