diff --git a/ChangeLog b/ChangeLog index 6190b74e..7e9d08dd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2009-08-03 + * Added support for $weather_forecast (experimental) + 2009-08-01 * Added support for out_to_ncurses diff --git a/doc/variables.xml b/doc/variables.xml index b797373d..8b969a76 100644 --- a/doc/variables.xml +++ b/doc/variables.xml @@ -540,7 +540,10 @@ - Change drawing color to color + Change drawing color to 'color' which is a name of + a color or a hexcode preceded with # (for example #0A1B2C ). + If you use ncurses only the following colors are supported: + red,green,yellow,blue,magenta,cyan,black,white. @@ -3423,6 +3426,79 @@ and can be subject to many future changes. + + + + + + + + + Download, parse and display weather forecast data + for a given day (daytime only). + For the 'URI', for the time being only + http://xoap.weather.com/weather/local/ is + supported. See 'weather' above for details of usage + 'locID', see 'weather' above. + 'day' is a number from 0 (today) to 4 (3 days + after tomorrow). + 'data_type' must be one of the following: + + + low + + + + high + + + + icon + + + + forecast + + + + wind_speed + + + + wind_dir + + + + wind_dir_DEG + + + + humidity + + + + precipitation + + + + 'delay_in_minutes' (optional, default 150) cannot + be lower than 150 min. + This object is threaded, and once a thread is + created it can't be explicitely destroyed. One thread + will run for each URI specified. You can use any + protocol that Curl supports. + Note that these variables are still EXPERIMENTAL + and can be subject to many future changes. + + diff --git a/src/conky.c b/src/conky.c index da733326..d26cb78f 100644 --- a/src/conky.c +++ b/src/conky.c @@ -68,6 +68,9 @@ #ifdef NCURSES #include #endif +#ifdef XOAP +#include +#endif /* XOAP */ /* local headers */ #include "algebra.h" @@ -992,6 +995,12 @@ static void free_text_objects(struct text_object *root, int internal) free(data.weather.data_type); break; #endif +#ifdef XOAP + case OBJ_weather_forecast: + free(data.weather_forecast.uri); + free(data.weather_forecast.data_type); + break; +#endif #ifdef HAVE_LUA case OBJ_lua: case OBJ_lua_parse: @@ -1780,6 +1789,30 @@ static struct text_object *construct_text_object(const char *s, current_text_color = obj->data.l; } #endif /* X11 */ +#ifdef NCURSES + if (output_methods & TO_NCURSES) { + obj->data.l = COLOR_WHITE; + if(arg) { + if(strcasecmp(arg, "red") == 0) { + obj->data.l = COLOR_RED; + }else if(strcasecmp(arg, "green") == 0) { + obj->data.l = COLOR_GREEN; + }else if(strcasecmp(arg, "yellow") == 0) { + obj->data.l = COLOR_YELLOW; + }else if(strcasecmp(arg, "blue") == 0) { + obj->data.l = COLOR_BLUE; + }else if(strcasecmp(arg, "magenta") == 0) { + obj->data.l = COLOR_MAGENTA; + }else if(strcasecmp(arg, "cyan") == 0) { + obj->data.l = COLOR_CYAN; + }else if(strcasecmp(arg, "black") == 0) { + obj->data.l = COLOR_BLACK; + } + } + current_text_color = obj->data.l; + init_pair(obj->data.l, obj->data.l, COLOR_BLACK); + } +#endif /* NCURSES */ END OBJ(color0, 0) obj->data.l = color0; current_text_color = obj->data.l; @@ -2985,7 +3018,7 @@ static struct text_object *construct_text_object(const char *s, argc = sscanf(arg, "%119s %8s %31s %f", uri, locID, data_type, &interval); if (argc >= 3) { - if (process_weather_uri(uri, locID)) { + if (process_weather_uri(uri, locID, 0)) { free(data_type); free(uri); free(locID); @@ -3017,6 +3050,57 @@ static struct text_object *construct_text_object(const char *s, CRIT_ERR(obj, free_at_crash, "weather needs arguments: [interval in minutes]"); } #endif +#ifdef XOAP + END OBJ(weather_forecast, 0) + if (arg) { + int argc; + unsigned int day; + float interval = 0; + char *locID = (char *) malloc(9 * sizeof(char)); + char *uri = (char *) malloc(128 * sizeof(char)); + char *data_type = (char *) malloc(32 * sizeof(char)); + + argc = sscanf(arg, "%119s %8s %1u %31s %f", uri, locID, &day, data_type, &interval); + + if (argc >= 4) { + if (process_weather_uri(uri, locID, 1)) { + free(data_type); + free(uri); + free(locID); + CRIT_ERR(obj, free_at_crash, \ + "could not recognize the weather forecast uri"); + } + + obj->data.weather_forecast.uri = uri; + obj->data.weather_forecast.data_type = data_type; + + /* Limit the day between 0 (today) and FORECAST_DAYS */ + if (day >= FORECAST_DAYS) { + day = FORECAST_DAYS-1; + } + obj->data.weather_forecast.day = day; + + /* Limit the data retrieval interval to 2 hours and an half */ + if (interval < 150) { + interval = 150; + } + + /* Convert to seconds */ + obj->data.weather_forecast.interval = interval * 60; + free(locID); + + DBGP("weather_forecast: fetching %s for day %d from %s every %d seconds", \ + data_type, day, uri, obj->data.weather_forecast.interval); + } else { + free(data_type); + free(uri); + free(locID); + CRIT_ERR(obj, free_at_crash, "wrong number of arguments for $weather_forecast"); + } + } else { + CRIT_ERR(obj, free_at_crash, "weather_forecast needs arguments: [interval in minutes]"); + } +#endif #ifdef HAVE_LUA END OBJ(lua, 0) if (arg) { @@ -4098,9 +4182,11 @@ static void generate_text_internal(char *p, int p_max_size, new_graph(p, obj->a, obj->b, obj->c, obj->d, cur->loadavg[0], obj->e, 1, obj->char_a, obj->char_b); } +#endif /* X11 */ OBJ(color) { new_fg(p, obj->data.l); } +#ifdef X11 OBJ(color0) { new_fg(p, color0); } @@ -4787,6 +4873,15 @@ static void generate_text_internal(char *p, int p_max_size, } } #endif +#ifdef XOAP + OBJ(weather_forecast) { + if (obj->data.weather_forecast.uri != NULL) { + weather_forecast_process_info(p, p_max_size, obj->data.weather_forecast.uri, obj->data.weather_forecast.day, obj->data.weather_forecast.data_type, obj->data.weather_forecast.interval); + } else { + NORM_ERR("error processing weather forecast data, check that you have a valid XOAP key if using XOAP."); + } + } +#endif #ifdef HAVE_LUA OBJ(lua) { char *str = llua_getstring(obj->data.s); @@ -6474,15 +6569,23 @@ static int text_size_updater(char *s, int special_index) last_font_height = font_height(); return special_index; } +#endif /* X11 */ static inline void set_foreground_color(long c) { - if ((output_methods & TO_X) == 0) - return; - current_color = c; - XSetForeground(display, window.gc, c); -} +#ifdef X11 + if (output_methods & TO_X) { + current_color = c; + XSetForeground(display, window.gc, c); + } #endif /* X11 */ +#ifdef NCURSES + if (output_methods & TO_NCURSES) { + attron(COLOR_PAIR(c)); + } +#endif /* NCURSES */ + return; +} static void draw_string(const char *s) { @@ -6519,7 +6622,7 @@ static void draw_string(const char *s) } #ifdef NCURSES if ((output_methods & TO_NCURSES) && draw_mode == FG) { - printw("%s\n", s_with_newlines); + printw("%s", s_with_newlines); } #endif free(s_with_newlines); @@ -6599,18 +6702,21 @@ static void draw_string(const char *s) memcpy(tmpstring1, s, text_buffer_size); } -#ifdef X11 int draw_each_line_inner(char *s, int special_index, int last_special_applied) { +#ifdef X11 int font_h = font_height(); int cur_y_add = 0; +#endif /* X11 */ char *recurse = 0; char *p = s; int last_special_needed = -1; int orig_special_index = special_index; +#ifdef X11 cur_x = text_start_x; cur_y += font_ascent(); +#endif /* X11 */ while (*p) { if (*p == SECRIT_MULTILINE_CHAR) { @@ -6620,7 +6726,9 @@ int draw_each_line_inner(char *s, int special_index, int last_special_applied) break; } if (*p == SPECIAL_CHAR || last_special_applied > -1) { +#ifdef X11 int w = 0; +#endif /* X11 */ /* draw string before special, unless we're dealing multiline * specials */ @@ -6634,6 +6742,7 @@ int draw_each_line_inner(char *s, int special_index, int last_special_applied) } /* draw special */ switch (specials[special_index].type) { +#ifdef X11 case HORIZONTAL_LINE: { int h = specials[special_index].height; @@ -6928,12 +7037,14 @@ int draw_each_line_inner(char *s, int special_index, int last_special_applied) font_h = font_height(); break; } +#endif /* X11 */ case FG: if (draw_mode == FG) { set_foreground_color(specials[special_index].arg); } break; +#ifdef X11 case BG: if (draw_mode == BG) { set_foreground_color(specials[special_index].arg); @@ -7015,9 +7126,12 @@ int draw_each_line_inner(char *s, int special_index, int last_special_applied) last_special_needed = special_index; break; } +#endif /* X11 */ } +#ifdef X11 cur_x += w; +#endif /* X11 */ if (special_index != last_special_applied) { special_index++; @@ -7029,31 +7143,40 @@ int draw_each_line_inner(char *s, int special_index, int last_special_applied) p++; } +#ifdef X11 cur_y += cur_y_add; +#endif /* X11 */ draw_string(s); +#ifdef NCURSES + if (output_methods & TO_NCURSES) { + printw("\n"); + } +#endif /* NCURSES */ +#ifdef X11 cur_y += font_descent(); +#endif /* X11 */ if (recurse && *recurse) { special_index = draw_each_line_inner(recurse, special_index, last_special_needed); *(recurse - 1) = SECRIT_MULTILINE_CHAR; } return special_index; } -#endif /* X11 */ static int draw_line(char *s, int special_index) { #ifdef X11 - if ((output_methods & TO_X) == 0) { -#endif /* X11 */ - draw_string(s); - //'special_index - special_index' instead of 0 otherwise gcc complains about not using special_index when build without X11 - return special_index - special_index; -#ifdef X11 + if (output_methods & TO_X) { + return draw_each_line_inner(s, special_index, -1); } - - /* find specials and draw stuff */ - return draw_each_line_inner(s, special_index, -1); #endif /* X11 */ +#ifdef NCURSES + if (output_methods & TO_NCURSES) { + return draw_each_line_inner(s, special_index, -1); + } +#endif /* NCURSES */ + draw_string(s); + //'special_index - special_index' instead of 0 otherwise gcc complains about not using special_index when build without X11 + return special_index - special_index; } static void draw_text(void) @@ -7088,6 +7211,10 @@ static void draw_text(void) } setup_fonts(); #endif /* X11 */ +#ifdef NCURSES + init_pair(COLOR_WHITE, COLOR_WHITE, COLOR_BLACK); + attron(COLOR_PAIR(COLOR_WHITE)); +#endif /* NCURSES */ for_each_line(text_buffer, draw_line); #if defined(HAVE_LUA) && defined(X11) llua_draw_post_hook(); @@ -7790,6 +7917,9 @@ void clean_up(void *memtofree1, void* memtofree2) #ifdef IMLIB2 cimlib_deinit(); #endif /* IMLIB2 */ +#ifdef XOAP + xmlCleanupParser(); +#endif /* XOAP */ if (specials) { for (i = 0; i < special_count; i++) { @@ -8499,6 +8629,7 @@ char load_config_file(const char *f) CONF("out_to_ncurses") { if(string_to_bool(value)) { initscr(); + start_color(); output_methods |= TO_NCURSES; } } @@ -9415,6 +9546,9 @@ void initialisation(int argc, char **argv) { #ifdef HAVE_LUA llua_setup_info(&info, update_interval); #endif /* HAVE_LUA */ +#ifdef XOAP + xmlInitParser(); +#endif /* XOAP */ /* Set signal handlers */ act.sa_handler = signal_handler; diff --git a/src/specials.c b/src/specials.c index a76cd417..71df3de0 100644 --- a/src/specials.c +++ b/src/specials.c @@ -351,15 +351,21 @@ void new_stippled_hr(char *buf, int a, int b) s->height = b; s->arg = a; } +#endif /* X11 */ void new_fg(char *buf, long c) { - if ((output_methods & TO_X) == 0) - return; - - new_special(buf, FG)->arg = c; +#ifdef X11 + if (output_methods & TO_X) + new_special(buf, FG)->arg = c; +#endif /* X11 */ +#ifdef NCURSES + if (output_methods & TO_NCURSES) + new_special(buf, FG)->arg = c; +#endif /* NCURSES */ } +#ifdef X11 void new_bg(char *buf, long c) { if ((output_methods & TO_X) == 0) diff --git a/src/text_object.h b/src/text_object.h index 46d62ff0..519c3184 100644 --- a/src/text_object.h +++ b/src/text_object.h @@ -386,6 +386,9 @@ enum text_object_type { #ifdef WEATHER OBJ_weather, #endif /* WEATHER */ +#ifdef XOAP + OBJ_weather_forecast, +#endif /* XOAP */ #ifdef HAVE_LUA OBJ_lua, OBJ_lua_parse, @@ -561,6 +564,14 @@ struct text_object { char *data_type; int interval; } weather; +#endif +#ifdef XOAP + struct { + char *uri; + unsigned int day; + char *data_type; + int interval; + } weather_forecast; #endif struct { char *text; diff --git a/src/weather.c b/src/weather.c index a2141d8e..671d5265 100644 --- a/src/weather.c +++ b/src/weather.c @@ -24,11 +24,6 @@ * */ -/* - * TODO: Add weather forecast info from weather.com - * - */ - #include "conky.h" #include "logging.h" #include "weather.h" @@ -44,12 +39,20 @@ #include /* Xpath expressions for XOAP xml parsing */ -#define NUM_XPATH_EXPRESSIONS 8 -const char *xpath_expression[NUM_XPATH_EXPRESSIONS] = { +#define NUM_XPATH_EXPRESSIONS_CC 8 +const char *xpath_expression_cc[NUM_XPATH_EXPRESSIONS_CC] = { "/weather/cc/lsup", "/weather/cc/tmp", "/weather/cc/t", "/weather/cc/bar/r", "/weather/cc/wind/s", "/weather/cc/wind/d", "/weather/cc/hmid", "/weather/cc/icon" }; + +#define NUM_XPATH_EXPRESSIONS_DF 8 +const char *xpath_expression_df[NUM_XPATH_EXPRESSIONS_DF] = { + "/weather/dayf/day[*]/hi", "/weather/dayf/day[*]/low", + "/weather/dayf/day[*]/part[1]/icon", "/weather/dayf/day[*]/part[1]/t", + "/weather/dayf/day[*]/part[1]/wind/s","/weather/dayf/day[*]/part[1]/wind/d", + "/weather/dayf/day[*]/part[1]/ppcp", "/weather/dayf/day[*]/part[1]/hmid" +}; #endif /* XOAP */ /* Possible sky conditions */ @@ -73,11 +76,17 @@ const char *WC_CODES[NUM_WC_CODES] = { "FC", "PO", "SQ", "SS", "DS" }; -static ccurl_location_t *locations_head = 0; +static ccurl_location_t *locations_head_cc = 0; +#ifdef XOAP +static ccurl_location_t *locations_head_df = 0; +#endif void weather_free_info(void) { - ccurl_free_locations(&locations_head); + ccurl_free_locations(&locations_head_cc); +#ifdef XOAP + ccurl_free_locations(&locations_head_df); +#endif } int rel_humidity(int dew_point, int air) { @@ -93,46 +102,113 @@ int rel_humidity(int dew_point, int air) { } #ifdef XOAP +static void parse_df(PWEATHER_FORECAST *res, xmlXPathContextPtr xpathCtx) +{ + int i, j, k; + char *content; + xmlXPathObjectPtr xpathObj; + + for (i = 0; i < NUM_XPATH_EXPRESSIONS_DF; i++) { + xpathObj = xmlXPathEvalExpression((xmlChar *)xpath_expression_df[i], xpathCtx); + if (xpathObj != NULL) { + xmlNodeSetPtr nodes = xpathObj->nodesetval; + k = 0; + for (j = 0; j < nodes->nodeNr; ++j) { + if (nodes->nodeTab[j]->type == XML_ELEMENT_NODE) { + content = (char *)xmlNodeGetContent(nodes->nodeTab[k]); + switch(i) { + case 0: + res->hi[k] = atoi(content); + break; + case 1: + res->low[k] = atoi(content); + break; + case 2: + strncpy(res->icon[k], content, 2); + case 3: + strncpy(res->xoap_t[k], content, 31); + break; + case 4: + res->wind_s[k] = atoi(content); + break; + case 5: + res->wind_d[k] = atoi(content); + break; + case 6: + res->ppcp[k] = atoi(content); + break; + case 7: + res->hmid[k] = atoi(content); + } + xmlFree(content); + if (++k == FORECAST_DAYS) break; + } + } + xmlXPathFreeObject(xpathObj); + } + } + return; +} + +static void parse_weather_forecast_xml(PWEATHER_FORECAST *res, const char *data) +{ + xmlDocPtr doc; + xmlXPathContextPtr xpathCtx; + + if (!(doc = xmlReadMemory(data, strlen(data), "", NULL, 0))) { + NORM_ERR("weather_forecast: can't read xml data"); + return; + } + + xpathCtx = xmlXPathNewContext(doc); + if(xpathCtx == NULL) { + NORM_ERR("weather_forecast: unable to create new XPath context"); + xmlFreeDoc(doc); + return; + } + + parse_df(res, xpathCtx); + xmlXPathFreeContext(xpathCtx); + xmlFreeDoc(doc); + return; +} + static void parse_cc(PWEATHER *res, xmlXPathContextPtr xpathCtx) { int i; char *content; xmlXPathObjectPtr xpathObj; - for (i = 0; i < NUM_XPATH_EXPRESSIONS; i++) { - xpathObj = xmlXPathEvalExpression((xmlChar *)xpath_expression[i], xpathCtx); + for (i = 0; i < NUM_XPATH_EXPRESSIONS_CC; i++) { + xpathObj = xmlXPathEvalExpression((xmlChar *)xpath_expression_cc[i], xpathCtx); if ((xpathObj != NULL) && (xpathObj->nodesetval->nodeTab[0]->type == XML_ELEMENT_NODE)) { - content = (char *)xmlNodeGetContent(xpathObj->nodesetval->nodeTab[0]); - switch(i) { - case 0: - strncpy(res->lastupd, content, 31); - break; - case 1: - res->temp = atoi(content); - break; - case 2: - if(res->xoap_t[0] == '\0') { - strncpy(res->xoap_t, content, 31); - } - break; - case 3: - res->bar = atoi(content); - break; - case 4: - res->wind_s = atoi(content); - break; - case 5: - if (isdigit((char)content[0])) { - res->wind_d = atoi(content); - } - break; - case 6: - res->hmid = atoi(content); + content = (char *)xmlNodeGetContent(xpathObj->nodesetval->nodeTab[0]); + switch(i) { + case 0: + strncpy(res->lastupd, content, 31); break; - case 7: - strncpy(res->icon, content, 2); - } - xmlFree(content); + case 1: + res->temp = atoi(content); + break; + case 2: + strncpy(res->xoap_t, content, 31); + break; + case 3: + res->bar = atoi(content); + break; + case 4: + res->wind_s = atoi(content); + break; + case 5: + res->wind_d = atoi(content); + break; + case 6: + res->hmid = atoi(content); + break; + case 7: + strncpy(res->icon, content, 2); + } + xmlFree(content); } xmlXPathFreeObject(xpathObj); } @@ -453,6 +529,20 @@ static inline void parse_token(PWEATHER *res, char *token) { } } +#ifdef XOAP +void parse_weather_forecast(void *result, const char *data) +{ + PWEATHER_FORECAST *res = (PWEATHER_FORECAST*)result; + /* Reset results */ + memset(res, 0, sizeof(PWEATHER_FORECAST)); + + //Check if it is an xml file + if ( strncmp(data, "= 349) || (wind_deg < 12)) { + strncpy(p, "N", p_max_size); + } else if (wind_deg < 33) { + strncpy(p, "NNE", p_max_size); + } else if (wind_deg < 57) { + strncpy(p, "NE", p_max_size); + } else if (wind_deg < 79) { + strncpy(p, "ENE", p_max_size); + } else if (wind_deg < 102) { + strncpy(p, "E", p_max_size); + } else if (wind_deg < 124) { + strncpy(p, "ESE", p_max_size); + } else if (wind_deg < 147) { + strncpy(p, "SE", p_max_size); + } else if (wind_deg < 169) { + strncpy(p, "SSE", p_max_size); + } else if (wind_deg < 192) { + strncpy(p, "S", p_max_size); + } else if (wind_deg < 214) { + strncpy(p, "SSW", p_max_size); + } else if (wind_deg < 237) { + strncpy(p, "SW", p_max_size); + } else if (wind_deg < 259) { + strncpy(p, "WSW", p_max_size); + } else if (wind_deg < 282) { + strncpy(p, "W", p_max_size); + } else if (wind_deg < 304) { + strncpy(p, "WNW", p_max_size); + } else if (wind_deg < 327) { + strncpy(p, "NW", p_max_size); + } else if (wind_deg < 349) { + strncpy(p, "NNW", p_max_size); + }; +} + +#ifdef XOAP +void weather_forecast_process_info(char *p, int p_max_size, char *uri, unsigned int day, char *data_type, int interval) +{ + PWEATHER_FORECAST *data; + + ccurl_location_t *curloc = ccurl_find_location(&locations_head_df, uri); + if (!curloc->p_timed_thread) { + curloc->result = malloc(sizeof(PWEATHER_FORECAST)); + memset(curloc->result, 0, sizeof(PWEATHER_FORECAST)); + curloc->process_function = &parse_weather_forecast; + ccurl_init_thread(curloc, interval); + if (!curloc->p_timed_thread) { + NORM_ERR("error setting up weather_forecast thread"); + } + } + + timed_thread_lock(curloc->p_timed_thread); + data = (PWEATHER_FORECAST*)curloc->result; + if (strcmp(data_type, "hi") == EQUAL) { + temp_print(p, p_max_size, data->hi[day], TEMP_CELSIUS); + } else if (strcmp(data_type, "low") == EQUAL) { + temp_print(p, p_max_size, data->low[day], TEMP_CELSIUS); + } else if (strcmp(data_type, "icon") == EQUAL) { + strncpy(p, data->icon[day], p_max_size); + } else if (strcmp(data_type, "forecast") == EQUAL) { + strncpy(p, data->xoap_t[day], p_max_size); + } else if (strcmp(data_type, "wind_speed") == EQUAL) { + snprintf(p, p_max_size, "%d", data->wind_s[day]); + } else if (strcmp(data_type, "wind_dir") == EQUAL) { + wind_deg_to_dir(p, p_max_size, data->wind_d[day]); + } else if (strcmp(data_type, "wind_dir_DEG") == EQUAL) { + snprintf(p, p_max_size, "%d", data->wind_d[day]); + } else if (strcmp(data_type, "humidity") == EQUAL) { + snprintf(p, p_max_size, "%d", data->hmid[day]); + } else if (strcmp(data_type, "precipitation") == EQUAL) { + snprintf(p, p_max_size, "%d", data->ppcp[day]); + } + + timed_thread_unlock(curloc->p_timed_thread); +} +#endif /* XOAP */ + void weather_process_info(char *p, int p_max_size, char *uri, char *data_type, int interval) { static const char *wc[] = { @@ -507,7 +675,7 @@ void weather_process_info(char *p, int p_max_size, char *uri, char *data_type, i }; PWEATHER *data; - ccurl_location_t *curloc = ccurl_find_location(&locations_head, uri); + ccurl_location_t *curloc = ccurl_find_location(&locations_head_cc, uri); if (!curloc->p_timed_thread) { curloc->result = malloc(sizeof(PWEATHER)); memset(curloc->result, 0, sizeof(PWEATHER)); @@ -554,39 +722,7 @@ void weather_process_info(char *p, int p_max_size, char *uri, char *data_type, i } else if (strcmp(data_type, "wind_speed") == EQUAL) { snprintf(p, p_max_size, "%d", data->wind_s); } else if (strcmp(data_type, "wind_dir") == EQUAL) { - if ((data->wind_d >= 349) || (data->wind_d < 12)) { - strncpy(p, "N", p_max_size); - } else if (data->wind_d < 33) { - strncpy(p, "NNE", p_max_size); - } else if (data->wind_d < 57) { - strncpy(p, "NE", p_max_size); - } else if (data->wind_d < 79) { - strncpy(p, "ENE", p_max_size); - } else if (data->wind_d < 102) { - strncpy(p, "E", p_max_size); - } else if (data->wind_d < 124) { - strncpy(p, "ESE", p_max_size); - } else if (data->wind_d < 147) { - strncpy(p, "SE", p_max_size); - } else if (data->wind_d < 169) { - strncpy(p, "SSE", p_max_size); - } else if (data->wind_d < 192) { - strncpy(p, "S", p_max_size); - } else if (data->wind_d < 214) { - strncpy(p, "SSW", p_max_size); - } else if (data->wind_d < 237) { - strncpy(p, "SW", p_max_size); - } else if (data->wind_d < 259) { - strncpy(p, "WSW", p_max_size); - } else if (data->wind_d < 282) { - strncpy(p, "W", p_max_size); - } else if (data->wind_d < 304) { - strncpy(p, "WNW", p_max_size); - } else if (data->wind_d < 327) { - strncpy(p, "NW", p_max_size); - } else if (data->wind_d < 349) { - strncpy(p, "NNW", p_max_size); - }; + wind_deg_to_dir(p, p_max_size, data->wind_d); } else if (strcmp(data_type, "wind_dir_DEG") == EQUAL) { snprintf(p, p_max_size, "%d", data->wind_d); @@ -602,7 +738,8 @@ void weather_process_info(char *p, int p_max_size, char *uri, char *data_type, i #ifdef XOAP /* xoap suffix for weather from weather.com */ -static char *xoap = NULL; +static char *xoap_cc = NULL; +static char *xoap_df = NULL; /* * TODO: make the xoap keys file readable from the config file @@ -612,34 +749,39 @@ static char *xoap = NULL; void load_xoap_keys(void) { FILE *fp; - char *par = (char *) malloc(11 * sizeof(char)); - char *key = (char *) malloc(17 * sizeof(char)); + char *par = (char *) malloc(11 * sizeof(char)); + char *key = (char *) malloc(17 * sizeof(char)); + char *xoap = (char *) malloc(64 * sizeof(char)); - xoap = (char *) malloc(64 * sizeof(char)); to_real_path(xoap, XOAP_FILE); fp = fopen(xoap, "r"); if (fp != NULL) { if (fscanf(fp, "%10s %16s", par, key) == 2) { - strcpy(xoap, "?cc=*&link=xoap&prod=xoap&par="); - strcat(xoap, par); - strcat(xoap, "&key="); - strcat(xoap, key); - strcat(xoap, "&unit=m"); - } else { - free(xoap); - xoap = NULL; + xoap_cc = (char *) malloc(128 * sizeof(char)); + xoap_df = (char *) malloc(128 * sizeof(char)); + + strcpy(xoap_cc, "?cc=*&link=xoap&prod=xoap&par="); + strcat(xoap_cc, par); + strcat(xoap_cc, "&key="); + strcat(xoap_cc, key); + strcat(xoap_cc, "&unit=m"); + + /* TODO: Use FORECAST_DAYS instead of 5 */ + strcpy(xoap_df, "?dayf=5&link=xoap&prod=xoap&par="); + strcat(xoap_df, par); + strcat(xoap_df, "&key="); + strcat(xoap_df, key); + strcat(xoap_df, "&unit=m"); } fclose(fp); - } else { - free(xoap); - xoap = NULL; } free(par); free(key); + free(xoap); } #endif /* XOAP */ -int process_weather_uri(char *uri, char *locID) +int process_weather_uri(char *uri, char *locID, int dayf) { /* locID MUST BE upper-case */ char *tmp_p = locID; @@ -651,9 +793,12 @@ int process_weather_uri(char *uri, char *locID) /* Construct complete uri */ #ifdef XOAP if (strstr(uri, "xoap.weather.com")) { - if (xoap != NULL) { + if ((dayf == 0) && (xoap_cc != NULL)) { strcat(uri, locID); - strcat(uri, xoap); + strcat(uri, xoap_cc); + } else if ((dayf == 1) && (xoap_df != NULL)) { + strcat(uri, locID); + strcat(uri, xoap_df); } else { free(uri); uri = NULL; @@ -668,4 +813,3 @@ int process_weather_uri(char *uri, char *locID) } return 0; } - diff --git a/src/weather.h b/src/weather.h index fa418d0e..d70ec196 100644 --- a/src/weather.h +++ b/src/weather.h @@ -49,10 +49,27 @@ typedef struct PWEATHER_ { int wc; } PWEATHER; +#ifdef XOAP +#define FORECAST_DAYS 5 +typedef struct PWEATHER_FORECAST_ { + int hi[FORECAST_DAYS]; + int low[FORECAST_DAYS]; + char icon[FORECAST_DAYS][3]; + char xoap_t[FORECAST_DAYS][32]; + int wind_s[FORECAST_DAYS]; + int wind_d[FORECAST_DAYS]; + int hmid[FORECAST_DAYS]; + int ppcp[FORECAST_DAYS]; +} PWEATHER_FORECAST; +#endif /* XOAP */ + /* Prototypes */ void weather_free_info(void); void weather_process_info(char *p, int p_max_size, char *uri, char *data_type, int interval); -int process_weather_uri(char *uri, char *locID); +#ifdef XOAP +void weather_forecast_process_info(char *p, int p_max_size, char *uri, unsigned int day, char *data_type, int interval); +#endif /* XOAP */ +int process_weather_uri(char *uri, char *locID, int dayf); #ifdef XOAP void load_xoap_keys(void);