David Smart / NWSWeather
Revision:
0:4435c965d95d
Child:
1:e077d6502c94
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NWSWeather.cpp	Sun Mar 16 15:37:16 2014 +0000
@@ -0,0 +1,259 @@
+
+#include "NWSWeather.h"
+
+
+static XMLItem_T WeatherData[] = {
+    {"observation_time_rfc822", isString, false, NULL},
+    {"suggested_pickup", isString, false, NULL},
+    {"suggested_pickup_period", isInt, false, 0},
+    {"location", isString, false, NULL},
+    {"weather", isString, false, NULL},
+    {"temp_f",  isFloat, false, 0},
+    {"temp_c",  isFloat, false, 0},
+    {"relative_humidity", isInt, false, 0},
+    {"wind_degrees", isInt, false, 0},
+    {"wind_mph", isFloat, false, 0},
+    {"pressure_mb", isFloat},
+    {"pressure_in", isFloat, false, 0},
+    {"dewpoint_f", isFloat},
+    {"dewpoint_c", isFloat},
+    {"windchill_f", isInt, false, 0},
+    {"windchill_c", isInt, false, 0},
+    {"visibility_mi", isFloat},
+    {"icon_url_base", isString, false, NULL},
+    {"icon_url_name", isString, false, NULL},
+    {"latitude", isFloat, false, 0},
+    {"longitude", isFloat, false, 0},
+};
+
+#define MAXPARAMLEN 23
+
+#define WeatherItemCount (sizeof(WeatherData)/sizeof(WeatherData[0]))
+
+NWSWeather::NWSWeather(const char * baseURL)
+{
+    setAlternateURL(baseURL);
+}
+
+NWSWeather::~NWSWeather()
+{
+    ClearWeatherRecords();
+}
+
+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;
+}
+
+NWSReturnCode_T NWSWeather::get(const char * site, int responseSize)
+{
+    Timer timer;
+    char *message = (char *)malloc(responseSize);
+
+    if (message) {
+        char * url = (char *)malloc(strlen(m_baseurl) + strlen(site) + 5);
+        if (url) {
+            strcpy(url, m_baseurl);
+            strcat(url, site);
+            strcat(url, ".xml");
+            http.setMaxRedirections(3);
+            //printf("get(%s)\r\n", url);
+            timer.start();
+            int ret = http.get(url, message, responseSize);
+            int elapsed = timer.read_ms();
+            if (!ret) {
+                if (http.getHTTPResponseCode() >= 300 && http.getHTTPResponseCode() < 400) {
+                    return noerror;         // redirection that was not satisfied.
+                } else {
+                    ParseWeatherXML(message);
+                    return noerror;
+                }
+            } else {
+                return noresponse;
+            }
+        } else {
+            return nomemory;
+        }
+    }
+    return nomemory;
+}
+
+
+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;
+    }
+}
+
+
+NWSReturnCode_T NWSWeather::isUpdated(uint16_t i)
+{
+    if (i < WeatherItemCount && WeatherData[i].updated)
+        return noerror;
+    else
+        return noupdate;
+}
+
+
+NWSReturnCode_T NWSWeather::getParam(const char *name, Value_T *value, TypeOf_T *typeis)
+{
+    if (value) {
+        for (int i=0; i < WeatherItemCount; i++) {
+            //printf("Compare(%s,%s)\r\n", name, WeatherData[i].name);
+            if (strcmp(name, WeatherData[i].name) == 0) {
+                *value = WeatherData[i].value;
+                //printf("  assignment.\r\n");
+                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);
+    }
+}
+
+NWSReturnCode_T NWSWeather::ParseWeatherRecord(char * p)
+{
+    // <tag_name>value</tag_name>
+    //  p1       p2   p3
+    char *p1, *p2, *p3;
+    int i;
+    int count = WeatherItemCount;
+
+    //printf("::%s::\r\n", p);
+    p1 = strchr(p, '<');
+    if (p1++) {
+        p2 = strchr(p1+1, '>');
+        if (p2) {
+            p3 = strchr(p2+1, '<');
+            if (p3) {
+                *p2++ = '\0';
+                *p3 = '\0';
+                //printf("tag: %s, value: %s\r\n", p1, p2);
+                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;
+                        }
+                        //PrintWeatherRecord(i);
+                        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;
+        }
+    }
+}