2009-07-28 21:44:22 +00:00
|
|
|
/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*-
|
2009-09-12 10:50:51 +00:00
|
|
|
* vim: ts=4 sw=4 noet ai cindent syntax=c
|
2009-07-28 21:44:22 +00:00
|
|
|
*
|
2009-07-13 05:31:57 +00:00
|
|
|
* Conky, a system monitor, based on torsmo
|
2009-07-06 22:20:12 +00:00
|
|
|
*
|
|
|
|
* Please see COPYING for details
|
|
|
|
*
|
2010-01-01 23:46:17 +00:00
|
|
|
* Copyright (c) 2005-2010 Brenden Matthews, Philip Kovacs, et. al.
|
2009-07-06 22:20:12 +00:00
|
|
|
* (see AUTHORS)
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2009-10-04 17:42:01 +00:00
|
|
|
#include "config.h"
|
2009-07-06 22:20:12 +00:00
|
|
|
#include "conky.h"
|
|
|
|
#include "logging.h"
|
|
|
|
#include "weather.h"
|
2009-07-13 05:31:57 +00:00
|
|
|
#include "temphelper.h"
|
2009-10-04 17:42:01 +00:00
|
|
|
#include "text_object.h"
|
2009-07-20 05:43:36 +00:00
|
|
|
#include "ccurl_thread.h"
|
2009-07-06 22:20:12 +00:00
|
|
|
#include <time.h>
|
|
|
|
#include <ctype.h>
|
2010-01-04 04:50:02 +00:00
|
|
|
#include <mutex>
|
2009-07-18 05:57:04 +00:00
|
|
|
#ifdef MATH
|
|
|
|
#include <math.h>
|
|
|
|
#endif /* MATH */
|
2010-01-07 02:38:12 +00:00
|
|
|
#ifdef BUILD_WEATHER_XOAP
|
Revert "Undid last 3 commits, see rest of the comment for the reason:"
First of all, we may or may not agree, but I consider reverting my
commits without prior discussion as a minimum unpolite.
I also don't like sites that oblige to register, thats the very reason
why I went with noaa first (and why I use that myself).
Howver, weather.com has a couple of nice features forom an user
viewpoint:
1. Their icons can be used to add a visual quality to the weather
report.
2. They have forecast data, which is not possible to have with noaa
(using TAF its an option, but its going to be very difficult and will
be limited in time and scope).
Nobody is obliged to do anything, people who likes noaa will use noaa,
people that don't mind register or wants the additional benefit will use
weather.com.
Having libxms2 as a dragged depends is, first of all, also with other
options (rss and eve), second we can try to work around it with an
additional compilation flag if really deemed necessary.
This reverts commit d872562942812a7c71245acf7cc5f028bd4b7b4d.
2009-07-18 17:13:37 +00:00
|
|
|
#include <libxml/parser.h>
|
2009-07-23 21:46:23 +00:00
|
|
|
#include <libxml/xpath.h>
|
2010-01-07 02:38:12 +00:00
|
|
|
#endif /* BUILD_WEATHER_XOAP */
|
2009-07-23 21:46:23 +00:00
|
|
|
|
2009-10-04 17:42:01 +00:00
|
|
|
/* WEATHER data */
|
|
|
|
typedef struct PWEATHER_ {
|
|
|
|
char lastupd[32];
|
2010-01-07 02:38:12 +00:00
|
|
|
#ifdef BUILD_WEATHER_XOAP
|
2009-10-04 17:42:01 +00:00
|
|
|
char xoap_t[32];
|
|
|
|
char icon[3];
|
2010-01-07 02:38:12 +00:00
|
|
|
#endif /* BUILD_WEATHER_XOAP */
|
2009-10-04 17:42:01 +00:00
|
|
|
int temp;
|
|
|
|
int dew;
|
|
|
|
int cc;
|
|
|
|
int bar;
|
|
|
|
int wind_s;
|
|
|
|
int wind_d;
|
|
|
|
int hmid;
|
|
|
|
int wc;
|
|
|
|
} PWEATHER;
|
|
|
|
|
2010-01-07 02:38:12 +00:00
|
|
|
#ifdef BUILD_WEATHER_XOAP
|
2009-10-04 17:42:01 +00:00
|
|
|
#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];
|
|
|
|
char day[FORECAST_DAYS][9];
|
|
|
|
char date[FORECAST_DAYS][7];
|
|
|
|
int wind_s[FORECAST_DAYS];
|
|
|
|
int wind_d[FORECAST_DAYS];
|
|
|
|
int hmid[FORECAST_DAYS];
|
|
|
|
int ppcp[FORECAST_DAYS];
|
|
|
|
} PWEATHER_FORECAST;
|
|
|
|
|
2010-01-07 02:38:12 +00:00
|
|
|
/* Xpath expressions for BUILD_WEATHER_XOAP xml parsing */
|
2009-08-02 21:54:44 +00:00
|
|
|
#define NUM_XPATH_EXPRESSIONS_CC 8
|
|
|
|
const char *xpath_expression_cc[NUM_XPATH_EXPRESSIONS_CC] = {
|
2009-07-23 21:46:23 +00:00
|
|
|
"/weather/cc/lsup", "/weather/cc/tmp", "/weather/cc/t",
|
|
|
|
"/weather/cc/bar/r", "/weather/cc/wind/s", "/weather/cc/wind/d",
|
2009-07-29 20:22:24 +00:00
|
|
|
"/weather/cc/hmid", "/weather/cc/icon"
|
2009-07-23 21:46:23 +00:00
|
|
|
};
|
2009-08-02 21:54:44 +00:00
|
|
|
|
2009-08-10 20:46:21 +00:00
|
|
|
#define NUM_XPATH_EXPRESSIONS_DF 10
|
2009-08-02 21:54:44 +00:00
|
|
|
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",
|
2009-08-10 20:46:21 +00:00
|
|
|
"/weather/dayf/day[*]/part[1]/ppcp", "/weather/dayf/day[*]/part[1]/hmid",
|
2009-08-11 14:10:35 +00:00
|
|
|
"/weather/dayf/day[*]/@t", "/weather/dayf/day[*]/@dt"
|
2009-08-02 21:54:44 +00:00
|
|
|
};
|
2010-01-07 02:38:12 +00:00
|
|
|
#endif /* BUILD_WEATHER_XOAP */
|
2009-07-06 22:20:12 +00:00
|
|
|
|
|
|
|
/* Possible sky conditions */
|
2009-07-07 09:13:07 +00:00
|
|
|
#define NUM_CC_CODES 6
|
2009-07-13 05:31:57 +00:00
|
|
|
const char *CC_CODES[NUM_CC_CODES] = {
|
|
|
|
"SKC", "CLR", "FEW", "SCT", "BKN", "OVC"
|
|
|
|
};
|
2009-07-06 22:20:12 +00:00
|
|
|
|
2009-07-07 10:08:24 +00:00
|
|
|
/* Possible weather modifiers */
|
|
|
|
#define NUM_WM_CODES 9
|
2009-07-13 05:31:57 +00:00
|
|
|
const char *WM_CODES[NUM_WM_CODES] = {
|
|
|
|
"VC", "MI", "BC", "PR", "TS", "BL",
|
|
|
|
"SH", "DR", "FZ"
|
|
|
|
};
|
2009-07-07 10:08:24 +00:00
|
|
|
|
2009-07-06 22:20:12 +00:00
|
|
|
/* Possible weather conditions */
|
|
|
|
#define NUM_WC_CODES 17
|
2009-07-13 05:31:57 +00:00
|
|
|
const char *WC_CODES[NUM_WC_CODES] = {
|
|
|
|
"DZ", "RA", "GR", "GS", "SN", "SG",
|
|
|
|
"FG", "HZ", "FU", "BR", "DU", "SA",
|
2009-07-18 19:29:27 +00:00
|
|
|
"FC", "PO", "SQ", "SS", "DS"
|
2009-07-06 22:20:12 +00:00
|
|
|
};
|
|
|
|
|
2010-01-04 04:50:02 +00:00
|
|
|
static ccurl_location_list locations_cc;
|
2010-01-07 02:38:12 +00:00
|
|
|
#ifdef BUILD_WEATHER_XOAP
|
2010-01-04 04:50:02 +00:00
|
|
|
static ccurl_location_list locations_df;
|
2009-08-02 21:54:44 +00:00
|
|
|
#endif
|
2009-07-06 22:20:12 +00:00
|
|
|
|
2009-10-04 18:52:05 +00:00
|
|
|
struct weather_data {
|
|
|
|
char uri[128];
|
|
|
|
char data_type[32];
|
|
|
|
int interval;
|
|
|
|
};
|
|
|
|
|
2010-01-07 02:38:12 +00:00
|
|
|
#ifdef BUILD_WEATHER_XOAP
|
2009-10-04 18:52:05 +00:00
|
|
|
struct weather_forecast_data {
|
|
|
|
char uri[128];
|
|
|
|
unsigned int day;
|
|
|
|
char data_type[32];
|
|
|
|
int interval;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2009-07-20 05:43:36 +00:00
|
|
|
void weather_free_info(void)
|
2009-07-06 22:20:12 +00:00
|
|
|
{
|
2010-01-04 04:50:02 +00:00
|
|
|
ccurl_free_locations(locations_cc);
|
2010-01-07 02:38:12 +00:00
|
|
|
#ifdef BUILD_WEATHER_XOAP
|
2010-01-04 04:50:02 +00:00
|
|
|
ccurl_free_locations(locations_df);
|
2009-08-02 21:54:44 +00:00
|
|
|
#endif
|
2009-07-06 22:20:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int rel_humidity(int dew_point, int air) {
|
2009-07-13 05:31:57 +00:00
|
|
|
const float a = 17.27f;
|
|
|
|
const float b = 237.7f;
|
2009-07-06 22:20:12 +00:00
|
|
|
|
2009-07-18 05:57:04 +00:00
|
|
|
float diff = a*(dew_point/(b+dew_point)-air/(b+air));
|
|
|
|
#ifdef MATH
|
|
|
|
return (int)(100.f*expf(diff));
|
|
|
|
#else
|
|
|
|
return (int)(16.666667163372f*(6.f+diff*(6.f+diff*(3.f+diff))));
|
|
|
|
#endif /* MATH */
|
2009-07-06 22:20:12 +00:00
|
|
|
}
|
|
|
|
|
2010-01-07 02:38:12 +00:00
|
|
|
#ifdef BUILD_WEATHER_XOAP
|
2009-08-02 21:54:44 +00:00
|
|
|
static void parse_df(PWEATHER_FORECAST *res, xmlXPathContextPtr xpathCtx)
|
|
|
|
{
|
|
|
|
int i, j, k;
|
2010-01-03 17:52:22 +00:00
|
|
|
char *content = NULL;
|
2009-08-02 21:54:44 +00:00
|
|
|
xmlXPathObjectPtr xpathObj;
|
|
|
|
|
2009-08-05 15:50:24 +00:00
|
|
|
xpathObj = xmlXPathEvalExpression((const xmlChar *)"/error/err", xpathCtx);
|
|
|
|
if (xpathObj && xpathObj->nodesetval && xpathObj->nodesetval->nodeNr > 0 &&
|
|
|
|
xpathObj->nodesetval->nodeTab[0]->type == XML_ELEMENT_NODE) {
|
|
|
|
content = (char *)xmlNodeGetContent(xpathObj->nodesetval->nodeTab[0]);
|
|
|
|
NORM_ERR("XOAP error: %s", content);
|
|
|
|
xmlFree(content);
|
|
|
|
xmlXPathFreeObject(xpathObj);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
xmlXPathFreeObject(xpathObj);
|
|
|
|
|
2009-08-02 21:54:44 +00:00
|
|
|
for (i = 0; i < NUM_XPATH_EXPRESSIONS_DF; i++) {
|
2009-08-05 03:15:08 +00:00
|
|
|
xpathObj = xmlXPathEvalExpression((const xmlChar *)xpath_expression_df[i], xpathCtx);
|
2009-08-02 21:54:44 +00:00
|
|
|
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);
|
|
|
|
}
|
2009-08-10 20:46:21 +00:00
|
|
|
} else if (nodes->nodeTab[j]->type == XML_ATTRIBUTE_NODE) {
|
|
|
|
content = (char *)xmlNodeGetContent(nodes->nodeTab[k]);
|
|
|
|
switch(i) {
|
|
|
|
case 8:
|
|
|
|
strncpy(res->day[k], content, 8);
|
|
|
|
break;
|
|
|
|
case 9:
|
|
|
|
strncpy(res->date[k], content, 6);
|
|
|
|
}
|
2009-08-02 21:54:44 +00:00
|
|
|
}
|
2009-08-10 20:46:21 +00:00
|
|
|
xmlFree(content);
|
|
|
|
if (++k == FORECAST_DAYS) break;
|
2009-08-02 21:54:44 +00:00
|
|
|
}
|
|
|
|
}
|
2009-08-10 20:46:21 +00:00
|
|
|
xmlXPathFreeObject(xpathObj);
|
2009-08-02 21:54:44 +00:00
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2009-07-23 21:46:23 +00:00
|
|
|
static void parse_cc(PWEATHER *res, xmlXPathContextPtr xpathCtx)
|
Revert "Undid last 3 commits, see rest of the comment for the reason:"
First of all, we may or may not agree, but I consider reverting my
commits without prior discussion as a minimum unpolite.
I also don't like sites that oblige to register, thats the very reason
why I went with noaa first (and why I use that myself).
Howver, weather.com has a couple of nice features forom an user
viewpoint:
1. Their icons can be used to add a visual quality to the weather
report.
2. They have forecast data, which is not possible to have with noaa
(using TAF its an option, but its going to be very difficult and will
be limited in time and scope).
Nobody is obliged to do anything, people who likes noaa will use noaa,
people that don't mind register or wants the additional benefit will use
weather.com.
Having libxms2 as a dragged depends is, first of all, also with other
options (rss and eve), second we can try to work around it with an
additional compilation flag if really deemed necessary.
This reverts commit d872562942812a7c71245acf7cc5f028bd4b7b4d.
2009-07-18 17:13:37 +00:00
|
|
|
{
|
2009-07-23 21:46:23 +00:00
|
|
|
int i;
|
|
|
|
char *content;
|
|
|
|
xmlXPathObjectPtr xpathObj;
|
|
|
|
|
2009-08-05 03:15:08 +00:00
|
|
|
xpathObj = xmlXPathEvalExpression((const xmlChar *)"/error/err", xpathCtx);
|
|
|
|
if (xpathObj && xpathObj->nodesetval && xpathObj->nodesetval->nodeNr > 0 &&
|
|
|
|
xpathObj->nodesetval->nodeTab[0]->type == XML_ELEMENT_NODE) {
|
|
|
|
content = (char *)xmlNodeGetContent(xpathObj->nodesetval->nodeTab[0]);
|
|
|
|
NORM_ERR("XOAP error: %s", content);
|
|
|
|
xmlFree(content);
|
|
|
|
xmlXPathFreeObject(xpathObj);
|
|
|
|
return;
|
|
|
|
}
|
2009-08-05 04:56:19 +00:00
|
|
|
xmlXPathFreeObject(xpathObj);
|
2009-08-05 03:15:08 +00:00
|
|
|
|
2009-08-02 21:54:44 +00:00
|
|
|
for (i = 0; i < NUM_XPATH_EXPRESSIONS_CC; i++) {
|
2009-08-05 03:15:08 +00:00
|
|
|
xpathObj = xmlXPathEvalExpression((const xmlChar *)xpath_expression_cc[i], xpathCtx);
|
|
|
|
if (xpathObj && xpathObj->nodesetval && xpathObj->nodesetval->nodeNr >0 &&
|
|
|
|
xpathObj->nodesetval->nodeTab[0]->type ==
|
|
|
|
XML_ELEMENT_NODE) {
|
2009-08-02 21:54:44 +00:00
|
|
|
content = (char *)xmlNodeGetContent(xpathObj->nodesetval->nodeTab[0]);
|
|
|
|
switch(i) {
|
2009-08-05 03:15:08 +00:00
|
|
|
case 0:
|
|
|
|
strncpy(res->lastupd, content, 31);
|
|
|
|
break;
|
|
|
|
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);
|
2009-08-02 21:54:44 +00:00
|
|
|
}
|
|
|
|
xmlFree(content);
|
2009-07-19 18:12:42 +00:00
|
|
|
}
|
2009-07-23 21:46:23 +00:00
|
|
|
xmlXPathFreeObject(xpathObj);
|
Revert "Undid last 3 commits, see rest of the comment for the reason:"
First of all, we may or may not agree, but I consider reverting my
commits without prior discussion as a minimum unpolite.
I also don't like sites that oblige to register, thats the very reason
why I went with noaa first (and why I use that myself).
Howver, weather.com has a couple of nice features forom an user
viewpoint:
1. Their icons can be used to add a visual quality to the weather
report.
2. They have forecast data, which is not possible to have with noaa
(using TAF its an option, but its going to be very difficult and will
be limited in time and scope).
Nobody is obliged to do anything, people who likes noaa will use noaa,
people that don't mind register or wants the additional benefit will use
weather.com.
Having libxms2 as a dragged depends is, first of all, also with other
options (rss and eve), second we can try to work around it with an
additional compilation flag if really deemed necessary.
This reverts commit d872562942812a7c71245acf7cc5f028bd4b7b4d.
2009-07-18 17:13:37 +00:00
|
|
|
}
|
2009-07-19 18:12:42 +00:00
|
|
|
return;
|
Revert "Undid last 3 commits, see rest of the comment for the reason:"
First of all, we may or may not agree, but I consider reverting my
commits without prior discussion as a minimum unpolite.
I also don't like sites that oblige to register, thats the very reason
why I went with noaa first (and why I use that myself).
Howver, weather.com has a couple of nice features forom an user
viewpoint:
1. Their icons can be used to add a visual quality to the weather
report.
2. They have forecast data, which is not possible to have with noaa
(using TAF its an option, but its going to be very difficult and will
be limited in time and scope).
Nobody is obliged to do anything, people who likes noaa will use noaa,
people that don't mind register or wants the additional benefit will use
weather.com.
Having libxms2 as a dragged depends is, first of all, also with other
options (rss and eve), second we can try to work around it with an
additional compilation flag if really deemed necessary.
This reverts commit d872562942812a7c71245acf7cc5f028bd4b7b4d.
2009-07-18 17:13:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void parse_weather_xml(PWEATHER *res, const char *data)
|
|
|
|
{
|
2009-07-19 18:12:42 +00:00
|
|
|
xmlDocPtr doc;
|
2009-07-23 21:46:23 +00:00
|
|
|
xmlXPathContextPtr xpathCtx;
|
2009-07-19 18:12:42 +00:00
|
|
|
|
|
|
|
if (!(doc = xmlReadMemory(data, strlen(data), "", NULL, 0))) {
|
2009-08-01 18:45:43 +00:00
|
|
|
NORM_ERR("weather: can't read xml data");
|
2009-07-19 18:12:42 +00:00
|
|
|
return;
|
Revert "Undid last 3 commits, see rest of the comment for the reason:"
First of all, we may or may not agree, but I consider reverting my
commits without prior discussion as a minimum unpolite.
I also don't like sites that oblige to register, thats the very reason
why I went with noaa first (and why I use that myself).
Howver, weather.com has a couple of nice features forom an user
viewpoint:
1. Their icons can be used to add a visual quality to the weather
report.
2. They have forecast data, which is not possible to have with noaa
(using TAF its an option, but its going to be very difficult and will
be limited in time and scope).
Nobody is obliged to do anything, people who likes noaa will use noaa,
people that don't mind register or wants the additional benefit will use
weather.com.
Having libxms2 as a dragged depends is, first of all, also with other
options (rss and eve), second we can try to work around it with an
additional compilation flag if really deemed necessary.
This reverts commit d872562942812a7c71245acf7cc5f028bd4b7b4d.
2009-07-18 17:13:37 +00:00
|
|
|
}
|
2009-07-19 18:12:42 +00:00
|
|
|
|
2009-07-23 21:46:23 +00:00
|
|
|
xpathCtx = xmlXPathNewContext(doc);
|
|
|
|
if(xpathCtx == NULL) {
|
2009-08-01 18:45:43 +00:00
|
|
|
NORM_ERR("weather: unable to create new XPath context");
|
2009-07-23 21:46:23 +00:00
|
|
|
xmlFreeDoc(doc);
|
|
|
|
return;
|
2009-07-19 18:12:42 +00:00
|
|
|
}
|
|
|
|
|
2009-07-23 21:46:23 +00:00
|
|
|
parse_cc(res, xpathCtx);
|
|
|
|
xmlXPathFreeContext(xpathCtx);
|
2009-07-19 18:12:42 +00:00
|
|
|
xmlFreeDoc(doc);
|
2009-07-23 21:46:23 +00:00
|
|
|
return;
|
Revert "Undid last 3 commits, see rest of the comment for the reason:"
First of all, we may or may not agree, but I consider reverting my
commits without prior discussion as a minimum unpolite.
I also don't like sites that oblige to register, thats the very reason
why I went with noaa first (and why I use that myself).
Howver, weather.com has a couple of nice features forom an user
viewpoint:
1. Their icons can be used to add a visual quality to the weather
report.
2. They have forecast data, which is not possible to have with noaa
(using TAF its an option, but its going to be very difficult and will
be limited in time and scope).
Nobody is obliged to do anything, people who likes noaa will use noaa,
people that don't mind register or wants the additional benefit will use
weather.com.
Having libxms2 as a dragged depends is, first of all, also with other
options (rss and eve), second we can try to work around it with an
additional compilation flag if really deemed necessary.
This reverts commit d872562942812a7c71245acf7cc5f028bd4b7b4d.
2009-07-18 17:13:37 +00:00
|
|
|
}
|
2010-01-07 02:38:12 +00:00
|
|
|
#endif /* BUILD_WEATHER_XOAP */
|
Revert "Undid last 3 commits, see rest of the comment for the reason:"
First of all, we may or may not agree, but I consider reverting my
commits without prior discussion as a minimum unpolite.
I also don't like sites that oblige to register, thats the very reason
why I went with noaa first (and why I use that myself).
Howver, weather.com has a couple of nice features forom an user
viewpoint:
1. Their icons can be used to add a visual quality to the weather
report.
2. They have forecast data, which is not possible to have with noaa
(using TAF its an option, but its going to be very difficult and will
be limited in time and scope).
Nobody is obliged to do anything, people who likes noaa will use noaa,
people that don't mind register or wants the additional benefit will use
weather.com.
Having libxms2 as a dragged depends is, first of all, also with other
options (rss and eve), second we can try to work around it with an
additional compilation flag if really deemed necessary.
This reverts commit d872562942812a7c71245acf7cc5f028bd4b7b4d.
2009-07-18 17:13:37 +00:00
|
|
|
|
2009-07-06 22:20:12 +00:00
|
|
|
/*
|
|
|
|
* Horrible hack to avoid using regexes
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
static inline void parse_token(PWEATHER *res, char *token) {
|
|
|
|
|
2009-07-13 05:31:57 +00:00
|
|
|
int i;
|
|
|
|
char s_tmp[64];
|
|
|
|
|
|
|
|
switch (strlen(token)) {
|
|
|
|
|
|
|
|
//Check all tokens 2 chars long
|
|
|
|
case 2:
|
|
|
|
|
|
|
|
//Check if token is a weather condition
|
|
|
|
for (i=0; i<2; i++) {
|
|
|
|
if (!isalpha(token[i])) break;
|
|
|
|
}
|
|
|
|
if (i==2) {
|
|
|
|
for(i=0; i<NUM_WC_CODES; i++) {
|
|
|
|
if (!strncmp(token, WC_CODES[i], 2)) {
|
|
|
|
res->wc=i+1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Check for CB
|
|
|
|
if (!strcmp(token, "CB")) {
|
|
|
|
res->cc = 8;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
//Check all tokens 3 chars long
|
|
|
|
case 3:
|
|
|
|
|
|
|
|
//Check if token is a modified weather condition
|
|
|
|
if ((token[0] == '+') || (token[0] == '-')) {
|
|
|
|
for (i=1; i<3; i++) {
|
|
|
|
if (!isalpha(token[i])) break;
|
|
|
|
}
|
|
|
|
if (i==3) {
|
|
|
|
for(i=0; i<NUM_WC_CODES; i++) {
|
|
|
|
if (!strncmp(&token[1], WC_CODES[i], 2)) {
|
|
|
|
res->wc=i+1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//Check for NCD or NSC
|
|
|
|
if ((!strcmp(token, "NCD")) || (!strcmp(token, "NSC"))) {
|
|
|
|
res->cc = 1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Check for TCU
|
|
|
|
if (!strcmp(token, "TCU")) {
|
|
|
|
res->cc = 7;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
//Check all tokens 4 chars long
|
|
|
|
case 4:
|
|
|
|
|
|
|
|
//Check if token is a modified weather condition
|
|
|
|
for(i=0; i<NUM_WM_CODES; i++) {
|
|
|
|
if (!strncmp(token, WM_CODES[i], 2)) {
|
|
|
|
for(i=0; i<NUM_WC_CODES; i++) {
|
|
|
|
if (!strncmp(&token[2], WC_CODES[i], 2)) {
|
|
|
|
res->wc=i+1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
//Check all tokens 5 chars long
|
|
|
|
case 5:
|
|
|
|
|
|
|
|
//Check for CAVOK
|
|
|
|
if (!strcmp(token, "CAVOK")) {
|
|
|
|
res->cc = 1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Check if token is the temperature
|
|
|
|
for (i=0; i<2; i++) {
|
|
|
|
if (!isdigit(token[i])) break;
|
|
|
|
}
|
|
|
|
if ((i==2) && (token[2] == '/')) {
|
|
|
|
for (i=3; i<5; i++) {
|
|
|
|
if (!isdigit(token[i])) break;
|
|
|
|
}
|
|
|
|
if (i==5) {
|
|
|
|
//First 2 digits gives the air temperature
|
|
|
|
res->temp=atoi(token);
|
|
|
|
|
|
|
|
//4th and 5th digits gives the dew point temperature
|
|
|
|
res->dew=atoi(&token[3]);
|
|
|
|
|
|
|
|
//Compute humidity
|
|
|
|
res->hmid = rel_humidity(res->dew, res->temp);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//Check if token is the pressure
|
|
|
|
if ((token[0] == 'Q') || (token[0] == 'A')) {
|
|
|
|
for (i=1; i<5; i++) {
|
|
|
|
if (!isdigit(token[i])) break;
|
|
|
|
}
|
|
|
|
if (i==5) {
|
|
|
|
if (token[0] == 'A') {
|
|
|
|
//Convert inches of mercury to mbar
|
|
|
|
res->bar = (int)(atoi(&token[1])*0.338637526f);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Last 4 digits is pressure im mbar
|
|
|
|
res->bar = atoi(&token[1]);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//Check if token is a modified weather condition
|
|
|
|
if ((token[0] == '+') || (token[0] == '-')) {
|
|
|
|
for(i=0; i<NUM_WM_CODES; i++) {
|
|
|
|
if (!strncmp(&token[1], WM_CODES[i], 2)) {
|
|
|
|
for(i=0; i<NUM_WC_CODES; i++) {
|
|
|
|
if (!strncmp(&token[3], WC_CODES[i], 2)) {
|
|
|
|
res->wc=i+1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
//Check all tokens 6 chars long
|
|
|
|
case 6:
|
|
|
|
|
|
|
|
//Check if token is the cloud cover
|
|
|
|
for (i=0; i<3; i++) {
|
|
|
|
if (!isalpha(token[i])) break;
|
|
|
|
}
|
|
|
|
if (i==3) {
|
|
|
|
for (i=3; i<6; i++) {
|
|
|
|
if (!isdigit(token[i])) break;
|
|
|
|
}
|
|
|
|
if (i==6) {
|
|
|
|
//Check if first 3 digits gives the cloud cover condition
|
|
|
|
for(i=0; i<NUM_CC_CODES; i++) {
|
|
|
|
if (!strncmp(token, CC_CODES[i], 3)) {
|
|
|
|
res->cc=i+1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//Check if token is positive temp and negative dew
|
|
|
|
for (i=0; i<2; i++) {
|
|
|
|
if (!isdigit(token[i])) break;
|
|
|
|
}
|
|
|
|
if ((i==2) && (token[2] == '/') && (token[3] == 'M')) {
|
|
|
|
for (i=4; i<6; i++) {
|
|
|
|
if (!isdigit(token[i])) break;
|
|
|
|
}
|
|
|
|
if (i==6) {
|
|
|
|
//1st and 2nd digits gives the temperature
|
|
|
|
res->temp = atoi(token);
|
|
|
|
|
|
|
|
//5th and 6th digits gives the dew point temperature
|
|
|
|
res->dew = -atoi(&token[4]);
|
|
|
|
|
|
|
|
//Compute humidity
|
|
|
|
res->hmid = rel_humidity(res->dew, res->temp);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
//Check all tokens 7 chars long
|
|
|
|
case 7:
|
|
|
|
|
|
|
|
//Check if token is the observation time
|
|
|
|
for (i=0; i<6; i++) {
|
|
|
|
if (!isdigit(token[i])) break;
|
|
|
|
}
|
|
|
|
if ((i==6) && (token[6] == 'Z')) return;
|
|
|
|
|
|
|
|
//Check if token is the wind speed/direction in knots
|
|
|
|
for (i=0; i<5; i++) {
|
|
|
|
if (!isdigit(token[i])) break;
|
|
|
|
}
|
|
|
|
if ((i==5) && (token[5] == 'K') && (token[6] == 'T')) {
|
|
|
|
|
|
|
|
//First 3 digits are wind direction
|
|
|
|
strncpy(s_tmp, token, 3);
|
Revert "Undid last 3 commits, see rest of the comment for the reason:"
First of all, we may or may not agree, but I consider reverting my
commits without prior discussion as a minimum unpolite.
I also don't like sites that oblige to register, thats the very reason
why I went with noaa first (and why I use that myself).
Howver, weather.com has a couple of nice features forom an user
viewpoint:
1. Their icons can be used to add a visual quality to the weather
report.
2. They have forecast data, which is not possible to have with noaa
(using TAF its an option, but its going to be very difficult and will
be limited in time and scope).
Nobody is obliged to do anything, people who likes noaa will use noaa,
people that don't mind register or wants the additional benefit will use
weather.com.
Having libxms2 as a dragged depends is, first of all, also with other
options (rss and eve), second we can try to work around it with an
additional compilation flag if really deemed necessary.
This reverts commit d872562942812a7c71245acf7cc5f028bd4b7b4d.
2009-07-18 17:13:37 +00:00
|
|
|
s_tmp[3]='\0';
|
2009-07-13 05:31:57 +00:00
|
|
|
res->wind_d=atoi(s_tmp);
|
|
|
|
|
|
|
|
//4th and 5th digit are wind speed in knots (convert to km/hr)
|
|
|
|
res->wind_s = (int)(atoi(&token[3])*1.852);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Check if token is negative temperature
|
|
|
|
if ((token[0] == 'M') && (token[4] == 'M')) {
|
|
|
|
for (i=1; i<3; i++) {
|
|
|
|
if (!isdigit(token[i])) break;
|
|
|
|
}
|
|
|
|
if ((i==3) && (token[3] == '/')) {
|
|
|
|
for (i=5; i<7; i++) {
|
|
|
|
if (!isdigit(token[i])) break;
|
|
|
|
}
|
|
|
|
if (i==7) {
|
|
|
|
//2nd and 3rd digits gives the temperature
|
|
|
|
res->temp = -atoi(&token[1]);
|
|
|
|
|
|
|
|
//6th and 7th digits gives the dew point temperature
|
|
|
|
res->dew = -atoi(&token[5]);
|
|
|
|
|
|
|
|
//Compute humidity
|
|
|
|
res->hmid = rel_humidity(res->dew, res->temp);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//Check if token is wind variability
|
|
|
|
for (i=0; i<3; i++) {
|
|
|
|
if (!isdigit(token[i])) break;
|
|
|
|
}
|
|
|
|
if ((i==3) && (token[3] == 'V')) {
|
|
|
|
for (i=4; i<7; i++) {
|
|
|
|
if (!isdigit(token[i])) break;
|
|
|
|
}
|
|
|
|
if (i==7) return;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
//Check all tokens 8 chars long
|
|
|
|
case 8:
|
|
|
|
|
|
|
|
//Check if token is the wind speed/direction in m/s
|
|
|
|
for (i=0; i<5; i++) {
|
|
|
|
if (!isdigit(token[i])) break;
|
|
|
|
}
|
|
|
|
if ((i==5)&&(token[5] == 'M')&&(token[6] == 'P')&&(token[7] == 'S')) {
|
|
|
|
|
|
|
|
//First 3 digits are wind direction
|
|
|
|
strncpy(s_tmp, token, 3);
|
Revert "Undid last 3 commits, see rest of the comment for the reason:"
First of all, we may or may not agree, but I consider reverting my
commits without prior discussion as a minimum unpolite.
I also don't like sites that oblige to register, thats the very reason
why I went with noaa first (and why I use that myself).
Howver, weather.com has a couple of nice features forom an user
viewpoint:
1. Their icons can be used to add a visual quality to the weather
report.
2. They have forecast data, which is not possible to have with noaa
(using TAF its an option, but its going to be very difficult and will
be limited in time and scope).
Nobody is obliged to do anything, people who likes noaa will use noaa,
people that don't mind register or wants the additional benefit will use
weather.com.
Having libxms2 as a dragged depends is, first of all, also with other
options (rss and eve), second we can try to work around it with an
additional compilation flag if really deemed necessary.
This reverts commit d872562942812a7c71245acf7cc5f028bd4b7b4d.
2009-07-18 17:13:37 +00:00
|
|
|
s_tmp[3]='\0';
|
2009-07-13 05:31:57 +00:00
|
|
|
res->wind_d=atoi(s_tmp);
|
|
|
|
|
|
|
|
//4th and 5th digit are wind speed in m/s (convert to km/hr)
|
|
|
|
res->wind_s = (int)(atoi(&token[3])*3.6);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
//printf("token : %s\n", token);
|
|
|
|
break;
|
2009-07-07 09:13:07 +00:00
|
|
|
}
|
2009-07-13 05:31:57 +00:00
|
|
|
}
|
2009-07-06 22:20:12 +00:00
|
|
|
|
2010-01-07 02:38:12 +00:00
|
|
|
#ifdef BUILD_WEATHER_XOAP
|
2009-08-02 21:54:44 +00:00
|
|
|
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, "<?xml ", 6) == 0 ) {
|
|
|
|
parse_weather_forecast_xml(res, data);
|
|
|
|
}
|
|
|
|
}
|
2010-01-07 02:38:12 +00:00
|
|
|
#endif /* BUILD_WEATHER_XOAP */
|
2009-08-02 21:54:44 +00:00
|
|
|
|
2009-07-20 05:43:36 +00:00
|
|
|
void parse_weather(void *result, const char *data)
|
2009-07-13 05:31:57 +00:00
|
|
|
{
|
2009-07-20 05:43:36 +00:00
|
|
|
PWEATHER *res = (PWEATHER*)result;
|
|
|
|
/* Reset results */
|
2009-07-18 14:22:43 +00:00
|
|
|
memset(res, 0, sizeof(PWEATHER));
|
2009-07-06 22:20:12 +00:00
|
|
|
|
2010-01-07 02:38:12 +00:00
|
|
|
#ifdef BUILD_WEATHER_XOAP
|
Revert "Undid last 3 commits, see rest of the comment for the reason:"
First of all, we may or may not agree, but I consider reverting my
commits without prior discussion as a minimum unpolite.
I also don't like sites that oblige to register, thats the very reason
why I went with noaa first (and why I use that myself).
Howver, weather.com has a couple of nice features forom an user
viewpoint:
1. Their icons can be used to add a visual quality to the weather
report.
2. They have forecast data, which is not possible to have with noaa
(using TAF its an option, but its going to be very difficult and will
be limited in time and scope).
Nobody is obliged to do anything, people who likes noaa will use noaa,
people that don't mind register or wants the additional benefit will use
weather.com.
Having libxms2 as a dragged depends is, first of all, also with other
options (rss and eve), second we can try to work around it with an
additional compilation flag if really deemed necessary.
This reverts commit d872562942812a7c71245acf7cc5f028bd4b7b4d.
2009-07-18 17:13:37 +00:00
|
|
|
//Check if it is an xml file
|
|
|
|
if ( strncmp(data, "<?xml ", 6) == 0 ) {
|
2009-07-19 18:12:42 +00:00
|
|
|
parse_weather_xml(res, data);
|
2009-07-18 19:29:27 +00:00
|
|
|
} else
|
2010-01-07 02:38:12 +00:00
|
|
|
#endif /* BUILD_WEATHER_XOAP */
|
2009-07-19 18:12:42 +00:00
|
|
|
{
|
|
|
|
//We assume its a text file
|
|
|
|
char s_tmp[256];
|
|
|
|
const char delim[] = " ";
|
2009-07-07 09:13:07 +00:00
|
|
|
|
2009-07-19 18:12:42 +00:00
|
|
|
//Divide time stamp and metar data
|
|
|
|
if (sscanf(data, "%[^'\n']\n%[^'\n']", res->lastupd, s_tmp) == 2) {
|
2009-07-07 09:13:07 +00:00
|
|
|
|
2009-07-19 18:12:42 +00:00
|
|
|
//Process all tokens
|
|
|
|
char *p_tok = NULL;
|
|
|
|
char *p_save = NULL;
|
2009-07-07 09:13:07 +00:00
|
|
|
|
2009-07-19 18:12:42 +00:00
|
|
|
if ((strtok_r(s_tmp, delim, &p_save)) != NULL) {
|
2009-07-07 09:13:07 +00:00
|
|
|
|
2009-07-19 18:12:42 +00:00
|
|
|
//Jump first token, must be icao
|
|
|
|
p_tok = strtok_r(NULL, delim, &p_save);
|
2009-07-06 22:20:12 +00:00
|
|
|
|
2009-07-19 18:12:42 +00:00
|
|
|
do {
|
2009-07-18 13:59:43 +00:00
|
|
|
|
2009-07-19 18:12:42 +00:00
|
|
|
parse_token(res, p_tok);
|
|
|
|
p_tok = strtok_r(NULL, delim, &p_save);
|
Revert "Undid last 3 commits, see rest of the comment for the reason:"
First of all, we may or may not agree, but I consider reverting my
commits without prior discussion as a minimum unpolite.
I also don't like sites that oblige to register, thats the very reason
why I went with noaa first (and why I use that myself).
Howver, weather.com has a couple of nice features forom an user
viewpoint:
1. Their icons can be used to add a visual quality to the weather
report.
2. They have forecast data, which is not possible to have with noaa
(using TAF its an option, but its going to be very difficult and will
be limited in time and scope).
Nobody is obliged to do anything, people who likes noaa will use noaa,
people that don't mind register or wants the additional benefit will use
weather.com.
Having libxms2 as a dragged depends is, first of all, also with other
options (rss and eve), second we can try to work around it with an
additional compilation flag if really deemed necessary.
This reverts commit d872562942812a7c71245acf7cc5f028bd4b7b4d.
2009-07-18 17:13:37 +00:00
|
|
|
|
2009-07-19 18:12:42 +00:00
|
|
|
} while (p_tok != NULL);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2009-07-13 05:31:57 +00:00
|
|
|
}
|
2009-07-06 22:20:12 +00:00
|
|
|
|
2009-08-02 21:54:44 +00:00
|
|
|
void wind_deg_to_dir(char *p, int p_max_size, int wind_deg) {
|
|
|
|
if ((wind_deg >= 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);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2010-01-07 02:38:12 +00:00
|
|
|
#ifdef BUILD_WEATHER_XOAP
|
2009-10-04 17:42:01 +00:00
|
|
|
static void weather_forecast_process_info(char *p, int p_max_size, char *uri, unsigned int day, char *data_type, int interval)
|
2009-08-02 21:54:44 +00:00
|
|
|
{
|
|
|
|
PWEATHER_FORECAST *data;
|
|
|
|
|
2010-01-04 04:50:02 +00:00
|
|
|
ccurl_location_ptr curloc = ccurl_find_location(locations_df, uri);
|
2009-08-02 21:54:44 +00:00
|
|
|
if (!curloc->p_timed_thread) {
|
2010-01-04 04:50:02 +00:00
|
|
|
curloc->result = (char*)malloc(sizeof(PWEATHER_FORECAST));
|
2009-08-02 21:54:44 +00:00
|
|
|
memset(curloc->result, 0, sizeof(PWEATHER_FORECAST));
|
2010-01-04 04:50:02 +00:00
|
|
|
curloc->process_function = std::bind(parse_weather_forecast,
|
|
|
|
std::placeholders::_1, std::placeholders::_2);
|
2009-08-02 21:54:44 +00:00
|
|
|
ccurl_init_thread(curloc, interval);
|
|
|
|
if (!curloc->p_timed_thread) {
|
|
|
|
NORM_ERR("error setting up weather_forecast thread");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-04 04:50:02 +00:00
|
|
|
std::lock_guard<std::mutex> lock(curloc->p_timed_thread->mutex());
|
2009-08-02 21:54:44 +00:00
|
|
|
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]);
|
2009-08-10 20:46:21 +00:00
|
|
|
} else if (strcmp(data_type, "day") == EQUAL) {
|
|
|
|
strncpy(p, data->day[day], p_max_size);
|
|
|
|
} else if (strcmp(data_type, "date") == EQUAL) {
|
|
|
|
strncpy(p, data->date[day], p_max_size);
|
2009-08-02 21:54:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2010-01-07 02:38:12 +00:00
|
|
|
#endif /* BUILD_WEATHER_XOAP */
|
2009-08-02 21:54:44 +00:00
|
|
|
|
2009-10-04 17:42:01 +00:00
|
|
|
static void weather_process_info(char *p, int p_max_size, char *uri, char *data_type, int interval)
|
2009-07-06 22:20:12 +00:00
|
|
|
{
|
2009-07-13 05:31:57 +00:00
|
|
|
static const char *wc[] = {
|
|
|
|
"", "drizzle", "rain", "hail", "soft hail",
|
|
|
|
"snow", "snow grains", "fog", "haze", "smoke",
|
|
|
|
"mist", "dust", "sand", "funnel cloud tornado",
|
|
|
|
"dust/sand", "squall", "sand storm", "dust storm"
|
|
|
|
};
|
2009-07-20 05:43:36 +00:00
|
|
|
PWEATHER *data;
|
2009-07-13 05:31:57 +00:00
|
|
|
|
2010-01-04 04:50:02 +00:00
|
|
|
ccurl_location_ptr curloc = ccurl_find_location(locations_cc, uri);
|
2009-07-20 05:43:36 +00:00
|
|
|
if (!curloc->p_timed_thread) {
|
2010-01-04 04:50:02 +00:00
|
|
|
curloc->result = (char*)malloc(sizeof(PWEATHER));
|
2009-07-20 05:43:36 +00:00
|
|
|
memset(curloc->result, 0, sizeof(PWEATHER));
|
2010-01-04 04:50:02 +00:00
|
|
|
curloc->process_function = std::bind(parse_weather,
|
|
|
|
std::placeholders::_1, std::placeholders::_2);
|
2009-07-20 05:43:36 +00:00
|
|
|
ccurl_init_thread(curloc, interval);
|
|
|
|
if (!curloc->p_timed_thread) {
|
2009-08-01 18:45:43 +00:00
|
|
|
NORM_ERR("error setting up weather thread");
|
2009-07-20 05:43:36 +00:00
|
|
|
}
|
|
|
|
}
|
2009-07-13 05:31:57 +00:00
|
|
|
|
2010-01-04 04:50:02 +00:00
|
|
|
std::lock_guard<std::mutex> lock(curloc->p_timed_thread->mutex());
|
2009-07-20 05:43:36 +00:00
|
|
|
data = (PWEATHER*)curloc->result;
|
2009-07-13 05:31:57 +00:00
|
|
|
if (strcmp(data_type, "last_update") == EQUAL) {
|
2009-07-20 05:43:36 +00:00
|
|
|
strncpy(p, data->lastupd, p_max_size);
|
2009-07-13 05:31:57 +00:00
|
|
|
} else if (strcmp(data_type, "temperature") == EQUAL) {
|
2009-07-20 05:43:36 +00:00
|
|
|
temp_print(p, p_max_size, data->temp, TEMP_CELSIUS);
|
2009-07-13 05:31:57 +00:00
|
|
|
} else if (strcmp(data_type, "cloud_cover") == EQUAL) {
|
2010-01-07 02:38:12 +00:00
|
|
|
#ifdef BUILD_WEATHER_XOAP
|
2009-07-20 05:43:36 +00:00
|
|
|
if (data->xoap_t[0] != '\0') {
|
2009-08-05 03:15:08 +00:00
|
|
|
char *s = p;
|
2009-07-20 05:43:36 +00:00
|
|
|
strncpy(p, data->xoap_t, p_max_size);
|
2009-08-05 03:15:08 +00:00
|
|
|
while (*s) {
|
|
|
|
*s = tolower(*s);
|
|
|
|
s++;
|
|
|
|
}
|
2009-07-18 19:29:27 +00:00
|
|
|
} else
|
2010-01-07 02:38:12 +00:00
|
|
|
#endif /* BUILD_WEATHER_XOAP */
|
2009-07-20 05:43:36 +00:00
|
|
|
if (data->cc == 0) {
|
2009-07-19 18:12:42 +00:00
|
|
|
strncpy(p, "", p_max_size);
|
2009-07-20 05:43:36 +00:00
|
|
|
} else if (data->cc < 3) {
|
2009-07-19 18:12:42 +00:00
|
|
|
strncpy(p, "clear", p_max_size);
|
2009-07-20 05:43:36 +00:00
|
|
|
} else if (data->cc < 5) {
|
2009-07-19 18:12:42 +00:00
|
|
|
strncpy(p, "partly cloudy", p_max_size);
|
2009-07-20 05:43:36 +00:00
|
|
|
} else if (data->cc == 5) {
|
2009-07-19 18:12:42 +00:00
|
|
|
strncpy(p, "cloudy", p_max_size);
|
2009-07-20 05:43:36 +00:00
|
|
|
} else if (data->cc == 6) {
|
2009-07-19 18:12:42 +00:00
|
|
|
strncpy(p, "overcast", p_max_size);
|
2009-07-20 05:43:36 +00:00
|
|
|
} else if (data->cc == 7) {
|
2009-07-19 18:12:42 +00:00
|
|
|
strncpy(p, "towering cumulus", p_max_size);
|
|
|
|
} else {
|
|
|
|
strncpy(p, "cumulonimbus", p_max_size);
|
|
|
|
}
|
2010-01-07 02:38:12 +00:00
|
|
|
#ifdef BUILD_WEATHER_XOAP
|
2009-07-29 20:22:24 +00:00
|
|
|
} else if (strcmp(data_type, "icon") == EQUAL) {
|
|
|
|
strncpy(p, data->icon, p_max_size);
|
2010-01-07 02:38:12 +00:00
|
|
|
#endif /* BUILD_WEATHER_XOAP */
|
2009-07-13 05:31:57 +00:00
|
|
|
} else if (strcmp(data_type, "pressure") == EQUAL) {
|
2009-07-20 05:43:36 +00:00
|
|
|
snprintf(p, p_max_size, "%d", data->bar);
|
2009-07-13 05:31:57 +00:00
|
|
|
} else if (strcmp(data_type, "wind_speed") == EQUAL) {
|
2009-07-20 05:43:36 +00:00
|
|
|
snprintf(p, p_max_size, "%d", data->wind_s);
|
2009-07-13 05:31:57 +00:00
|
|
|
} else if (strcmp(data_type, "wind_dir") == EQUAL) {
|
2009-08-02 21:54:44 +00:00
|
|
|
wind_deg_to_dir(p, p_max_size, data->wind_d);
|
2009-07-13 05:31:57 +00:00
|
|
|
} else if (strcmp(data_type, "wind_dir_DEG") == EQUAL) {
|
2009-07-20 05:43:36 +00:00
|
|
|
snprintf(p, p_max_size, "%d", data->wind_d);
|
2009-07-13 05:31:57 +00:00
|
|
|
|
|
|
|
} else if (strcmp(data_type, "humidity") == EQUAL) {
|
2009-07-20 05:43:36 +00:00
|
|
|
snprintf(p, p_max_size, "%d", data->hmid);
|
2009-07-13 05:31:57 +00:00
|
|
|
} else if (strcmp(data_type, "weather") == EQUAL) {
|
2009-07-20 05:43:36 +00:00
|
|
|
strncpy(p, wc[data->wc], p_max_size);
|
2009-07-13 05:31:57 +00:00
|
|
|
}
|
Revert "Undid last 3 commits, see rest of the comment for the reason:"
First of all, we may or may not agree, but I consider reverting my
commits without prior discussion as a minimum unpolite.
I also don't like sites that oblige to register, thats the very reason
why I went with noaa first (and why I use that myself).
Howver, weather.com has a couple of nice features forom an user
viewpoint:
1. Their icons can be used to add a visual quality to the weather
report.
2. They have forecast data, which is not possible to have with noaa
(using TAF its an option, but its going to be very difficult and will
be limited in time and scope).
Nobody is obliged to do anything, people who likes noaa will use noaa,
people that don't mind register or wants the additional benefit will use
weather.com.
Having libxms2 as a dragged depends is, first of all, also with other
options (rss and eve), second we can try to work around it with an
additional compilation flag if really deemed necessary.
This reverts commit d872562942812a7c71245acf7cc5f028bd4b7b4d.
2009-07-18 17:13:37 +00:00
|
|
|
|
2009-07-06 22:20:12 +00:00
|
|
|
}
|
|
|
|
|
2010-01-07 02:38:12 +00:00
|
|
|
#ifdef BUILD_WEATHER_XOAP
|
2009-07-20 19:17:44 +00:00
|
|
|
/* xoap suffix for weather from weather.com */
|
2009-08-02 21:54:44 +00:00
|
|
|
static char *xoap_cc = NULL;
|
|
|
|
static char *xoap_df = NULL;
|
2010-01-07 02:38:12 +00:00
|
|
|
#endif /* BUILD_WEATHER_XOAP */
|
2009-07-20 19:17:44 +00:00
|
|
|
|
2009-10-04 17:42:01 +00:00
|
|
|
static int process_weather_uri(char *uri, char *locID, int dayf UNUSED_ATTR)
|
|
|
|
{
|
|
|
|
/* locID MUST BE upper-case */
|
|
|
|
char *tmp_p = locID;
|
|
|
|
|
|
|
|
while (*tmp_p) {
|
|
|
|
*tmp_p = toupper(*tmp_p);
|
|
|
|
tmp_p++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Construct complete uri */
|
2010-01-07 02:38:12 +00:00
|
|
|
#ifdef BUILD_WEATHER_XOAP
|
2009-10-04 17:42:01 +00:00
|
|
|
if (strstr(uri, "xoap.weather.com")) {
|
|
|
|
if ((dayf == 0) && (xoap_cc != NULL)) {
|
|
|
|
strcat(uri, locID);
|
|
|
|
strcat(uri, xoap_cc);
|
|
|
|
} else if ((dayf == 1) && (xoap_df != NULL)) {
|
|
|
|
strcat(uri, locID);
|
|
|
|
strcat(uri, xoap_df);
|
|
|
|
} else {
|
|
|
|
free(uri);
|
|
|
|
uri = NULL;
|
|
|
|
}
|
|
|
|
} else
|
2010-01-07 02:38:12 +00:00
|
|
|
#endif /* BUILD_WEATHER_XOAP */
|
2009-10-04 17:42:01 +00:00
|
|
|
if (strstr(uri, "weather.noaa.gov")) {
|
|
|
|
strcat(uri, locID);
|
|
|
|
strcat(uri, ".TXT");
|
|
|
|
} else if (!strstr(uri, "localhost") && !strstr(uri, "127.0.0.1")) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-01-07 02:38:12 +00:00
|
|
|
#ifdef BUILD_WEATHER_XOAP
|
2009-10-04 17:42:01 +00:00
|
|
|
|
2009-07-20 19:17:44 +00:00
|
|
|
/*
|
|
|
|
* TODO: make the xoap keys file readable from the config file
|
|
|
|
* make the keys directly readable from the config file
|
|
|
|
* make the xoap keys file giveable as a command line option
|
|
|
|
*/
|
|
|
|
void load_xoap_keys(void)
|
|
|
|
{
|
|
|
|
FILE *fp;
|
2009-08-02 22:24:39 +00:00
|
|
|
char *par = (char *) malloc(11 * sizeof(char));
|
|
|
|
char *key = (char *) malloc(17 * sizeof(char));
|
|
|
|
char *xoap = (char *) malloc(64 * sizeof(char));
|
2009-07-20 19:17:44 +00:00
|
|
|
|
|
|
|
to_real_path(xoap, XOAP_FILE);
|
|
|
|
fp = fopen(xoap, "r");
|
|
|
|
if (fp != NULL) {
|
|
|
|
if (fscanf(fp, "%10s %16s", par, key) == 2) {
|
2009-08-02 22:24:39 +00:00
|
|
|
xoap_cc = (char *) malloc(128 * sizeof(char));
|
|
|
|
xoap_df = (char *) malloc(128 * sizeof(char));
|
2009-08-02 21:54:44 +00:00
|
|
|
|
|
|
|
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");
|
|
|
|
|
2009-08-03 09:49:26 +00:00
|
|
|
/* TODO: Use FORECAST_DAYS instead of 5 */
|
2009-08-02 21:54:44 +00:00
|
|
|
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");
|
2009-07-20 19:17:44 +00:00
|
|
|
}
|
|
|
|
fclose(fp);
|
|
|
|
}
|
|
|
|
free(par);
|
|
|
|
free(key);
|
2009-08-02 22:24:39 +00:00
|
|
|
free(xoap);
|
2009-07-20 19:17:44 +00:00
|
|
|
}
|
|
|
|
|
2009-10-04 17:42:01 +00:00
|
|
|
void scan_weather_forecast_arg(struct text_object *obj, const char *arg, void *free_at_crash)
|
2009-07-20 19:17:44 +00:00
|
|
|
{
|
2009-10-04 17:42:01 +00:00
|
|
|
int argc;
|
2009-10-04 18:52:05 +00:00
|
|
|
struct weather_forecast_data *wfd;
|
2009-10-04 17:42:01 +00:00
|
|
|
float interval = 0;
|
|
|
|
char *locID = (char *) malloc(9 * sizeof(char));
|
|
|
|
|
2010-01-04 04:50:02 +00:00
|
|
|
wfd = (struct weather_forecast_data *)malloc(sizeof(struct weather_forecast_data));
|
2009-10-04 18:52:05 +00:00
|
|
|
memset(wfd, 0, sizeof(struct weather_forecast_data));
|
|
|
|
|
|
|
|
argc = sscanf(arg, "%119s %8s %1u %31s %f", wfd->uri, locID, &wfd->day, wfd->data_type, &interval);
|
2009-10-04 17:42:01 +00:00
|
|
|
|
|
|
|
if (argc < 4) {
|
|
|
|
free(locID);
|
2009-10-04 18:52:05 +00:00
|
|
|
free(wfd);
|
2009-10-04 17:42:01 +00:00
|
|
|
CRIT_ERR(obj, free_at_crash, "wrong number of arguments for $weather_forecast");
|
|
|
|
}
|
2009-10-04 18:52:05 +00:00
|
|
|
if (process_weather_uri(wfd->uri, locID, 1)) {
|
2009-10-04 17:42:01 +00:00
|
|
|
free(locID);
|
2009-10-04 18:52:05 +00:00
|
|
|
free(wfd);
|
2009-10-04 17:42:01 +00:00
|
|
|
CRIT_ERR(obj, free_at_crash, \
|
|
|
|
"could not recognize the weather forecast uri");
|
|
|
|
}
|
2009-08-03 18:56:41 +00:00
|
|
|
|
2009-10-04 17:42:01 +00:00
|
|
|
/* Limit the day between 0 (today) and FORECAST_DAYS */
|
2009-10-04 18:52:05 +00:00
|
|
|
if (wfd->day >= FORECAST_DAYS) {
|
|
|
|
wfd->day = FORECAST_DAYS-1;
|
2009-07-20 19:17:44 +00:00
|
|
|
}
|
|
|
|
|
2009-10-04 17:42:01 +00:00
|
|
|
/* Limit the data retrieval interval to 3 hours and an half */
|
|
|
|
if (interval < 210) {
|
|
|
|
interval = 210;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Convert to seconds */
|
2009-10-04 18:52:05 +00:00
|
|
|
wfd->interval = interval * 60;
|
2009-10-04 17:42:01 +00:00
|
|
|
free(locID);
|
|
|
|
|
|
|
|
DBGP("weather_forecast: fetching %s for day %d from %s every %d seconds", \
|
2009-10-04 18:52:05 +00:00
|
|
|
wfd->data_type, wfd->day, wfd->uri, wfd->interval);
|
2009-11-05 21:27:34 +00:00
|
|
|
|
|
|
|
obj->data.opaque = wfd;
|
2009-10-04 17:42:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void print_weather_forecast(struct text_object *obj, char *p, int p_max_size)
|
|
|
|
{
|
2010-01-04 04:50:02 +00:00
|
|
|
struct weather_forecast_data *wfd = (struct weather_forecast_data *)obj->data.opaque;
|
2009-10-04 18:52:05 +00:00
|
|
|
|
|
|
|
if (!wfd || !wfd->uri) {
|
2009-10-04 17:42:01 +00:00
|
|
|
NORM_ERR("error processing weather forecast data, check that you have a valid XOAP key if using XOAP.");
|
|
|
|
return;
|
|
|
|
}
|
2009-10-04 18:52:05 +00:00
|
|
|
weather_forecast_process_info(p, p_max_size, wfd->uri, wfd->day, wfd->data_type, wfd->interval);
|
2009-10-04 17:42:01 +00:00
|
|
|
}
|
2010-01-07 02:38:12 +00:00
|
|
|
#endif /* BUILD_WEATHER_XOAP */
|
2009-10-04 17:42:01 +00:00
|
|
|
|
|
|
|
void scan_weather_arg(struct text_object *obj, const char *arg, void *free_at_crash)
|
|
|
|
{
|
|
|
|
int argc;
|
2009-10-04 18:52:05 +00:00
|
|
|
struct weather_data *wd;
|
2009-10-04 17:42:01 +00:00
|
|
|
char *locID = (char *) malloc(9 * sizeof(char));
|
2009-10-04 18:52:05 +00:00
|
|
|
float interval = 0;
|
2009-10-04 17:42:01 +00:00
|
|
|
|
2010-01-04 04:50:02 +00:00
|
|
|
wd = (struct weather_data *)malloc(sizeof(struct weather_data));
|
2009-10-04 18:52:05 +00:00
|
|
|
memset(wd, 0, sizeof(struct weather_data));
|
|
|
|
|
|
|
|
argc = sscanf(arg, "%119s %8s %31s %f", wd->uri, locID, wd->data_type, &interval);
|
2009-10-04 17:42:01 +00:00
|
|
|
|
|
|
|
if (argc < 3) {
|
|
|
|
free(locID);
|
2009-10-04 18:52:05 +00:00
|
|
|
free(wd);
|
2009-10-04 17:42:01 +00:00
|
|
|
CRIT_ERR(obj, free_at_crash, "wrong number of arguments for $weather");
|
2009-07-20 19:17:44 +00:00
|
|
|
}
|
2009-10-04 18:52:05 +00:00
|
|
|
if (process_weather_uri(wd->uri, locID, 0)) {
|
2009-10-04 17:42:01 +00:00
|
|
|
free(locID);
|
2009-10-04 18:52:05 +00:00
|
|
|
free(wd);
|
2009-10-04 17:42:01 +00:00
|
|
|
CRIT_ERR(obj, free_at_crash, \
|
|
|
|
"could not recognize the weather uri");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Limit the data retrieval interval to half hour min */
|
|
|
|
if (interval < 30) {
|
|
|
|
interval = 30;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Convert to seconds */
|
2009-10-04 18:52:05 +00:00
|
|
|
wd->interval = interval * 60;
|
2009-10-04 17:42:01 +00:00
|
|
|
free(locID);
|
|
|
|
|
|
|
|
DBGP("weather: fetching %s from %s every %d seconds", \
|
2009-10-04 18:52:05 +00:00
|
|
|
wd->data_type, wd->uri, wd->interval);
|
2009-11-05 21:27:34 +00:00
|
|
|
|
|
|
|
obj->data.opaque = wd;
|
2009-10-04 17:42:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void print_weather(struct text_object *obj, char *p, int p_max_size)
|
|
|
|
{
|
2010-01-04 04:50:02 +00:00
|
|
|
struct weather_data *wd = (struct weather_data *)obj->data.opaque;
|
2009-10-04 18:52:05 +00:00
|
|
|
|
|
|
|
if (!wd || !wd->uri) {
|
2009-10-04 17:42:01 +00:00
|
|
|
NORM_ERR("error processing weather data, check that you have a valid XOAP key if using XOAP.");
|
|
|
|
return;
|
|
|
|
}
|
2009-10-04 18:52:05 +00:00
|
|
|
weather_process_info(p, p_max_size, wd->uri, wd->data_type, wd->interval);
|
|
|
|
}
|
|
|
|
|
|
|
|
void free_weather(struct text_object *obj)
|
|
|
|
{
|
|
|
|
if (obj->data.opaque) {
|
|
|
|
free(obj->data.opaque);
|
|
|
|
obj->data.opaque = NULL;
|
|
|
|
}
|
2009-07-20 19:17:44 +00:00
|
|
|
}
|