|
rpm-build |
ca2b01 |
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
rpm-build |
ca2b01 |
/* weather-metar.c - Weather server functions (METAR)
|
|
rpm-build |
ca2b01 |
*
|
|
rpm-build |
ca2b01 |
* This program is free software; you can redistribute it and/or
|
|
rpm-build |
ca2b01 |
* modify it under the terms of the GNU General Public License as
|
|
rpm-build |
ca2b01 |
* published by the Free Software Foundation; either version 2 of the
|
|
rpm-build |
ca2b01 |
* License, or (at your option) any later version.
|
|
rpm-build |
ca2b01 |
*
|
|
rpm-build |
ca2b01 |
* This program is distributed in the hope that it will be useful, but
|
|
rpm-build |
ca2b01 |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
rpm-build |
ca2b01 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
rpm-build |
ca2b01 |
* General Public License for more details.
|
|
rpm-build |
ca2b01 |
*
|
|
rpm-build |
ca2b01 |
* You should have received a copy of the GNU General Public License
|
|
rpm-build |
ca2b01 |
* along with this program; if not, see
|
|
rpm-build |
ca2b01 |
* <http://www.gnu.org/licenses/>.
|
|
rpm-build |
ca2b01 |
*/
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
#ifdef HAVE_CONFIG_H
|
|
rpm-build |
ca2b01 |
#include <config.h>
|
|
rpm-build |
ca2b01 |
#endif
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
#include <stdlib.h>
|
|
rpm-build |
ca2b01 |
#include <string.h>
|
|
rpm-build |
ca2b01 |
#include <sys/types.h>
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
#include "gweather-private.h"
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
enum {
|
|
rpm-build |
ca2b01 |
TIME_RE,
|
|
rpm-build |
ca2b01 |
WIND_RE,
|
|
rpm-build |
ca2b01 |
VIS_RE,
|
|
rpm-build |
ca2b01 |
COND_RE,
|
|
rpm-build |
ca2b01 |
CLOUD_RE,
|
|
rpm-build |
ca2b01 |
TEMP_RE,
|
|
rpm-build |
ca2b01 |
PRES_RE,
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
RE_NUM
|
|
rpm-build |
ca2b01 |
};
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
/* Return time of weather report as secs since epoch UTC */
|
|
rpm-build |
ca2b01 |
static time_t
|
|
rpm-build |
ca2b01 |
make_time (gint utcDate, gint utcHour, gint utcMin)
|
|
rpm-build |
ca2b01 |
{
|
|
rpm-build |
ca2b01 |
const time_t now = time (NULL);
|
|
rpm-build |
ca2b01 |
struct tm tm;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
localtime_r (&now, &tm;;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
/* If last reading took place just before midnight UTC on the
|
|
rpm-build |
ca2b01 |
* first, adjust the date downward to allow for the month
|
|
rpm-build |
ca2b01 |
* change-over. This ASSUMES that the reading won't be more than
|
|
rpm-build |
ca2b01 |
* 24 hrs old! */
|
|
rpm-build |
ca2b01 |
if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
|
|
rpm-build |
ca2b01 |
tm.tm_mday = 0; /* mktime knows this is the last day of the previous
|
|
rpm-build |
ca2b01 |
* month. */
|
|
rpm-build |
ca2b01 |
} else {
|
|
rpm-build |
ca2b01 |
tm.tm_mday = utcDate;
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
tm.tm_hour = utcHour;
|
|
rpm-build |
ca2b01 |
tm.tm_min = utcMin;
|
|
rpm-build |
ca2b01 |
tm.tm_sec = 0;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
/* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
|
|
rpm-build |
ca2b01 |
#ifdef HAVE_TM_TM_GMOFF
|
|
rpm-build |
ca2b01 |
return tm.tm_gmtoff + mktime (&tm;;
|
|
rpm-build |
ca2b01 |
#elif defined HAVE_TIMEZONE
|
|
rpm-build |
ca2b01 |
return timezone + mktime (&tm;;
|
|
rpm-build |
ca2b01 |
#endif
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
static void
|
|
rpm-build |
ca2b01 |
metar_tok_time (gchar *tokp, GWeatherInfo *info)
|
|
rpm-build |
ca2b01 |
{
|
|
rpm-build |
ca2b01 |
gint day, hr, min;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
|
|
rpm-build |
ca2b01 |
info->priv->update = make_time (day, hr, min);
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
static void
|
|
rpm-build |
ca2b01 |
metar_tok_wind (gchar *tokp, GWeatherInfo *info)
|
|
rpm-build |
ca2b01 |
{
|
|
rpm-build |
ca2b01 |
GWeatherInfoPrivate *priv;
|
|
rpm-build |
ca2b01 |
gchar sdir[4], sspd[4], sgust[4];
|
|
rpm-build |
ca2b01 |
gint dir, spd = -1;
|
|
rpm-build |
ca2b01 |
gchar *gustp;
|
|
rpm-build |
ca2b01 |
size_t glen;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
priv = info->priv;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
strncpy (sdir, tokp, 3);
|
|
rpm-build |
ca2b01 |
sdir[3] = 0;
|
|
rpm-build |
ca2b01 |
dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
memset (sspd, 0, sizeof (sspd));
|
|
rpm-build |
ca2b01 |
glen = strspn (tokp + 3, CONST_DIGITS);
|
|
rpm-build |
ca2b01 |
strncpy (sspd, tokp + 3, glen);
|
|
rpm-build |
ca2b01 |
spd = atoi (sspd);
|
|
rpm-build |
ca2b01 |
tokp += glen + 3;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
gustp = strchr (tokp, 'G');
|
|
rpm-build |
ca2b01 |
if (gustp) {
|
|
rpm-build |
ca2b01 |
memset (sgust, 0, sizeof (sgust));
|
|
rpm-build |
ca2b01 |
glen = strspn (gustp + 1, CONST_DIGITS);
|
|
rpm-build |
ca2b01 |
strncpy (sgust, gustp + 1, glen);
|
|
rpm-build |
ca2b01 |
tokp = gustp + 1 + glen;
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
if (!strcmp (tokp, "MPS"))
|
|
rpm-build |
ca2b01 |
priv->windspeed = WINDSPEED_MS_TO_KNOTS ((GWeatherWindSpeed)spd);
|
|
rpm-build |
ca2b01 |
else
|
|
rpm-build |
ca2b01 |
priv->windspeed = (GWeatherWindSpeed)spd;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
if ((349 <= dir) || (dir <= 11))
|
|
rpm-build |
ca2b01 |
priv->wind = GWEATHER_WIND_N;
|
|
rpm-build |
ca2b01 |
else if ((12 <= dir) && (dir <= 33))
|
|
rpm-build |
ca2b01 |
priv->wind = GWEATHER_WIND_NNE;
|
|
rpm-build |
ca2b01 |
else if ((34 <= dir) && (dir <= 56))
|
|
rpm-build |
ca2b01 |
priv->wind = GWEATHER_WIND_NE;
|
|
rpm-build |
ca2b01 |
else if ((57 <= dir) && (dir <= 78))
|
|
rpm-build |
ca2b01 |
priv->wind = GWEATHER_WIND_ENE;
|
|
rpm-build |
ca2b01 |
else if ((79 <= dir) && (dir <= 101))
|
|
rpm-build |
ca2b01 |
priv->wind = GWEATHER_WIND_E;
|
|
rpm-build |
ca2b01 |
else if ((102 <= dir) && (dir <= 123))
|
|
rpm-build |
ca2b01 |
priv->wind = GWEATHER_WIND_ESE;
|
|
rpm-build |
ca2b01 |
else if ((124 <= dir) && (dir <= 146))
|
|
rpm-build |
ca2b01 |
priv->wind = GWEATHER_WIND_SE;
|
|
rpm-build |
ca2b01 |
else if ((147 <= dir) && (dir <= 168))
|
|
rpm-build |
ca2b01 |
priv->wind = GWEATHER_WIND_SSE;
|
|
rpm-build |
ca2b01 |
else if ((169 <= dir) && (dir <= 191))
|
|
rpm-build |
ca2b01 |
priv->wind = GWEATHER_WIND_S;
|
|
rpm-build |
ca2b01 |
else if ((192 <= dir) && (dir <= 213))
|
|
rpm-build |
ca2b01 |
priv->wind = GWEATHER_WIND_SSW;
|
|
rpm-build |
ca2b01 |
else if ((214 <= dir) && (dir <= 236))
|
|
rpm-build |
ca2b01 |
priv->wind = GWEATHER_WIND_SW;
|
|
rpm-build |
ca2b01 |
else if ((237 <= dir) && (dir <= 258))
|
|
rpm-build |
ca2b01 |
priv->wind = GWEATHER_WIND_WSW;
|
|
rpm-build |
ca2b01 |
else if ((259 <= dir) && (dir <= 281))
|
|
rpm-build |
ca2b01 |
priv->wind = GWEATHER_WIND_W;
|
|
rpm-build |
ca2b01 |
else if ((282 <= dir) && (dir <= 303))
|
|
rpm-build |
ca2b01 |
priv->wind = GWEATHER_WIND_WNW;
|
|
rpm-build |
ca2b01 |
else if ((304 <= dir) && (dir <= 326))
|
|
rpm-build |
ca2b01 |
priv->wind = GWEATHER_WIND_NW;
|
|
rpm-build |
ca2b01 |
else if ((327 <= dir) && (dir <= 348))
|
|
rpm-build |
ca2b01 |
priv->wind = GWEATHER_WIND_NNW;
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
static void
|
|
rpm-build |
ca2b01 |
metar_tok_vis (gchar *tokp, GWeatherInfo *info)
|
|
rpm-build |
ca2b01 |
{
|
|
rpm-build |
ca2b01 |
GWeatherInfoPrivate *priv;
|
|
rpm-build |
ca2b01 |
gchar *pfrac, *pend, *psp;
|
|
rpm-build |
ca2b01 |
gchar sval[6];
|
|
rpm-build |
ca2b01 |
gint num, den, val;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
priv = info->priv;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
memset (sval, 0, sizeof (sval));
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
if (!strcmp (tokp,"CAVOK")) {
|
|
rpm-build |
ca2b01 |
// "Ceiling And Visibility OK": visibility >= 10 KM
|
|
rpm-build |
ca2b01 |
priv->visibility=10000. / VISIBILITY_SM_TO_M (1.);
|
|
rpm-build |
ca2b01 |
priv->sky = GWEATHER_SKY_CLEAR;
|
|
rpm-build |
ca2b01 |
} else if (0 != (pend = strstr (tokp, "SM"))) {
|
|
rpm-build |
ca2b01 |
// US observation: field ends with "SM"
|
|
rpm-build |
ca2b01 |
pfrac = strchr (tokp, '/');
|
|
rpm-build |
ca2b01 |
if (pfrac) {
|
|
rpm-build |
ca2b01 |
if (*tokp == 'M') {
|
|
rpm-build |
ca2b01 |
priv->visibility = 0.001;
|
|
rpm-build |
ca2b01 |
} else {
|
|
rpm-build |
ca2b01 |
num = (*(pfrac - 1) - '0');
|
|
rpm-build |
ca2b01 |
strncpy (sval, pfrac + 1, pend - pfrac - 1);
|
|
rpm-build |
ca2b01 |
den = atoi (sval);
|
|
rpm-build |
ca2b01 |
priv->visibility =
|
|
rpm-build |
ca2b01 |
((GWeatherVisibility)num / ((GWeatherVisibility)den));
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
psp = strchr (tokp, ' ');
|
|
rpm-build |
ca2b01 |
if (psp) {
|
|
rpm-build |
ca2b01 |
*psp = '\0';
|
|
rpm-build |
ca2b01 |
val = atoi (tokp);
|
|
rpm-build |
ca2b01 |
priv->visibility += (GWeatherVisibility)val;
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
} else {
|
|
rpm-build |
ca2b01 |
strncpy (sval, tokp, pend - tokp);
|
|
rpm-build |
ca2b01 |
val = atoi (sval);
|
|
rpm-build |
ca2b01 |
priv->visibility = (GWeatherVisibility)val;
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
} else {
|
|
rpm-build |
ca2b01 |
// International observation: NNNN(DD NNNNDD)?
|
|
rpm-build |
ca2b01 |
// For now: use only the minimum visibility and ignore its direction
|
|
rpm-build |
ca2b01 |
strncpy (sval, tokp, strspn (tokp, CONST_DIGITS));
|
|
rpm-build |
ca2b01 |
val = atoi (sval);
|
|
rpm-build |
ca2b01 |
priv->visibility = (GWeatherVisibility)val / VISIBILITY_SM_TO_M (1.);
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
static void
|
|
rpm-build |
ca2b01 |
metar_tok_cloud (gchar *tokp, GWeatherInfo *info)
|
|
rpm-build |
ca2b01 |
{
|
|
rpm-build |
ca2b01 |
GWeatherInfoPrivate *priv;
|
|
rpm-build |
ca2b01 |
gchar stype[4], salt[4];
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
priv = info->priv;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
strncpy (stype, tokp, 3);
|
|
rpm-build |
ca2b01 |
stype[3] = 0;
|
|
rpm-build |
ca2b01 |
if (strlen (tokp) == 6) {
|
|
rpm-build |
ca2b01 |
strncpy (salt, tokp + 3, 3);
|
|
rpm-build |
ca2b01 |
salt[3] = 0;
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
if (!strcmp (stype, "CLR")) {
|
|
rpm-build |
ca2b01 |
priv->sky = GWEATHER_SKY_CLEAR;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (stype, "SKC")) {
|
|
rpm-build |
ca2b01 |
priv->sky = GWEATHER_SKY_CLEAR;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (stype, "NSC")) {
|
|
rpm-build |
ca2b01 |
priv->sky = GWEATHER_SKY_CLEAR;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (stype, "BKN")) {
|
|
rpm-build |
ca2b01 |
priv->sky = GWEATHER_SKY_BROKEN;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (stype, "SCT")) {
|
|
rpm-build |
ca2b01 |
priv->sky = GWEATHER_SKY_SCATTERED;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (stype, "FEW")) {
|
|
rpm-build |
ca2b01 |
priv->sky = GWEATHER_SKY_FEW;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (stype, "OVC")) {
|
|
rpm-build |
ca2b01 |
priv->sky = GWEATHER_SKY_OVERCAST;
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
static void
|
|
rpm-build |
ca2b01 |
metar_tok_pres (gchar *tokp, GWeatherInfo *info)
|
|
rpm-build |
ca2b01 |
{
|
|
rpm-build |
ca2b01 |
GWeatherInfoPrivate *priv = info->priv;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
if (*tokp == 'A') {
|
|
rpm-build |
ca2b01 |
gchar sintg[3], sfract[3];
|
|
rpm-build |
ca2b01 |
gint intg, fract;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
strncpy (sintg, tokp + 1, 2);
|
|
rpm-build |
ca2b01 |
sintg[2] = 0;
|
|
rpm-build |
ca2b01 |
intg = atoi (sintg);
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
strncpy (sfract, tokp + 3, 2);
|
|
rpm-build |
ca2b01 |
sfract[2] = 0;
|
|
rpm-build |
ca2b01 |
fract = atoi (sfract);
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
priv->pressure = (GWeatherPressure)intg + (((GWeatherPressure)fract)/100.0);
|
|
rpm-build |
ca2b01 |
} else { /* *tokp == 'Q' */
|
|
rpm-build |
ca2b01 |
gchar spres[5];
|
|
rpm-build |
ca2b01 |
gint pres;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
strncpy (spres, tokp + 1, 4);
|
|
rpm-build |
ca2b01 |
spres[4] = 0;
|
|
rpm-build |
ca2b01 |
pres = atoi (spres);
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
priv->pressure = PRESSURE_MBAR_TO_INCH ((GWeatherPressure)pres);
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
static void
|
|
rpm-build |
ca2b01 |
metar_tok_temp (gchar *tokp, GWeatherInfo *info)
|
|
rpm-build |
ca2b01 |
{
|
|
rpm-build |
ca2b01 |
GWeatherInfoPrivate *priv;
|
|
rpm-build |
ca2b01 |
gchar *ptemp, *pdew, *psep;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
priv = info->priv;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
psep = strchr (tokp, '/');
|
|
rpm-build |
ca2b01 |
*psep = 0;
|
|
rpm-build |
ca2b01 |
ptemp = tokp;
|
|
rpm-build |
ca2b01 |
pdew = psep + 1;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
priv->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))
|
|
rpm-build |
ca2b01 |
: TEMP_C_TO_F (atoi (ptemp));
|
|
rpm-build |
ca2b01 |
if (*pdew) {
|
|
rpm-build |
ca2b01 |
priv->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))
|
|
rpm-build |
ca2b01 |
: TEMP_C_TO_F (atoi (pdew));
|
|
rpm-build |
ca2b01 |
} else {
|
|
rpm-build |
ca2b01 |
priv->dew = -1000.0;
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
/* How "important" are the conditions to be reported to the user.
|
|
rpm-build |
ca2b01 |
Indexed by GWeatherConditionPhenomenon */
|
|
rpm-build |
ca2b01 |
static const int importance_scale[] = {
|
|
rpm-build |
ca2b01 |
0, /* invalid */
|
|
rpm-build |
ca2b01 |
0, /* none */
|
|
rpm-build |
ca2b01 |
20, /* drizzle */
|
|
rpm-build |
ca2b01 |
30, /* rain */
|
|
rpm-build |
ca2b01 |
35, /* snow */
|
|
rpm-build |
ca2b01 |
35, /* snow grains */
|
|
rpm-build |
ca2b01 |
35, /* ice crystals */
|
|
rpm-build |
ca2b01 |
35, /* ice pellets */
|
|
rpm-build |
ca2b01 |
35, /* hail */
|
|
rpm-build |
ca2b01 |
35, /* small hail */
|
|
rpm-build |
ca2b01 |
20, /* unknown precipitation */
|
|
rpm-build |
ca2b01 |
10, /* mist */
|
|
rpm-build |
ca2b01 |
15, /* fog */
|
|
rpm-build |
ca2b01 |
15, /* smoke */
|
|
rpm-build |
ca2b01 |
18, /* volcanic ash */
|
|
rpm-build |
ca2b01 |
18, /* sand */
|
|
rpm-build |
ca2b01 |
15, /* haze */
|
|
rpm-build |
ca2b01 |
15, /* spray */
|
|
rpm-build |
ca2b01 |
15, /* dust */
|
|
rpm-build |
ca2b01 |
40, /* squall */
|
|
rpm-build |
ca2b01 |
50, /* sandstorm */
|
|
rpm-build |
ca2b01 |
50, /* duststorm */
|
|
rpm-build |
ca2b01 |
70, /* funnel cloud */
|
|
rpm-build |
ca2b01 |
70, /* tornado */
|
|
rpm-build |
ca2b01 |
50, /* dust whirls */
|
|
rpm-build |
ca2b01 |
};
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
static gboolean
|
|
rpm-build |
ca2b01 |
condition_more_important (GWeatherConditions *which,
|
|
rpm-build |
ca2b01 |
GWeatherConditions *than)
|
|
rpm-build |
ca2b01 |
{
|
|
rpm-build |
ca2b01 |
if (!than->significant)
|
|
rpm-build |
ca2b01 |
return TRUE;
|
|
rpm-build |
ca2b01 |
if (!which->significant)
|
|
rpm-build |
ca2b01 |
return FALSE;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
if (importance_scale[than->phenomenon] <
|
|
rpm-build |
ca2b01 |
importance_scale[which->phenomenon])
|
|
rpm-build |
ca2b01 |
return TRUE;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
return FALSE;
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
static void
|
|
rpm-build |
ca2b01 |
metar_tok_cond (gchar *tokp, GWeatherInfo *info)
|
|
rpm-build |
ca2b01 |
{
|
|
rpm-build |
ca2b01 |
GWeatherInfoPrivate *priv;
|
|
rpm-build |
ca2b01 |
GWeatherConditions new_cond;
|
|
rpm-build |
ca2b01 |
gchar squal[3], sphen[4];
|
|
rpm-build |
ca2b01 |
gchar *pphen;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
priv = info->priv;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
|
|
rpm-build |
ca2b01 |
++tokp; /* FIX */
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
if ((*tokp == '+') || (*tokp == '-'))
|
|
rpm-build |
ca2b01 |
pphen = tokp + 1;
|
|
rpm-build |
ca2b01 |
else if (strlen (tokp) < 4)
|
|
rpm-build |
ca2b01 |
pphen = tokp;
|
|
rpm-build |
ca2b01 |
else
|
|
rpm-build |
ca2b01 |
pphen = tokp + 2;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
memset (squal, 0, sizeof (squal));
|
|
rpm-build |
ca2b01 |
strncpy (squal, tokp, pphen - tokp);
|
|
rpm-build |
ca2b01 |
squal[pphen - tokp] = 0;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
memset (sphen, 0, sizeof (sphen));
|
|
rpm-build |
ca2b01 |
strncpy (sphen, pphen, sizeof (sphen));
|
|
rpm-build |
ca2b01 |
sphen[sizeof (sphen)-1] = '\0';
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
/* Defaults */
|
|
rpm-build |
ca2b01 |
new_cond.qualifier = GWEATHER_QUALIFIER_NONE;
|
|
rpm-build |
ca2b01 |
new_cond.phenomenon = GWEATHER_PHENOMENON_NONE;
|
|
rpm-build |
ca2b01 |
new_cond.significant = FALSE;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
if (!strcmp (squal, "")) {
|
|
rpm-build |
ca2b01 |
new_cond.qualifier = GWEATHER_QUALIFIER_MODERATE;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (squal, "-")) {
|
|
rpm-build |
ca2b01 |
new_cond.qualifier = GWEATHER_QUALIFIER_LIGHT;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (squal, "+")) {
|
|
rpm-build |
ca2b01 |
new_cond.qualifier = GWEATHER_QUALIFIER_HEAVY;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (squal, "VC")) {
|
|
rpm-build |
ca2b01 |
new_cond.qualifier = GWEATHER_QUALIFIER_VICINITY;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (squal, "MI")) {
|
|
rpm-build |
ca2b01 |
new_cond.qualifier = GWEATHER_QUALIFIER_SHALLOW;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (squal, "BC")) {
|
|
rpm-build |
ca2b01 |
new_cond.qualifier = GWEATHER_QUALIFIER_PATCHES;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (squal, "PR")) {
|
|
rpm-build |
ca2b01 |
new_cond.qualifier = GWEATHER_QUALIFIER_PARTIAL;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (squal, "TS")) {
|
|
rpm-build |
ca2b01 |
new_cond.qualifier = GWEATHER_QUALIFIER_THUNDERSTORM;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (squal, "BL")) {
|
|
rpm-build |
ca2b01 |
new_cond.qualifier = GWEATHER_QUALIFIER_BLOWING;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (squal, "SH")) {
|
|
rpm-build |
ca2b01 |
new_cond.qualifier = GWEATHER_QUALIFIER_SHOWERS;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (squal, "DR")) {
|
|
rpm-build |
ca2b01 |
new_cond.qualifier = GWEATHER_QUALIFIER_DRIFTING;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (squal, "FZ")) {
|
|
rpm-build |
ca2b01 |
new_cond.qualifier = GWEATHER_QUALIFIER_FREEZING;
|
|
rpm-build |
ca2b01 |
} else {
|
|
rpm-build |
ca2b01 |
return;
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
if (!strcmp (sphen, "DZ")) {
|
|
rpm-build |
ca2b01 |
new_cond.phenomenon = GWEATHER_PHENOMENON_DRIZZLE;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (sphen, "RA")) {
|
|
rpm-build |
ca2b01 |
new_cond.phenomenon = GWEATHER_PHENOMENON_RAIN;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (sphen, "SN")) {
|
|
rpm-build |
ca2b01 |
new_cond.phenomenon = GWEATHER_PHENOMENON_SNOW;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (sphen, "SG")) {
|
|
rpm-build |
ca2b01 |
new_cond.phenomenon = GWEATHER_PHENOMENON_SNOW_GRAINS;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (sphen, "IC")) {
|
|
rpm-build |
ca2b01 |
new_cond.phenomenon = GWEATHER_PHENOMENON_ICE_CRYSTALS;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (sphen, "PL")) {
|
|
rpm-build |
ca2b01 |
new_cond.phenomenon = GWEATHER_PHENOMENON_ICE_PELLETS;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (sphen, "GR")) {
|
|
rpm-build |
ca2b01 |
new_cond.phenomenon = GWEATHER_PHENOMENON_HAIL;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (sphen, "GS")) {
|
|
rpm-build |
ca2b01 |
new_cond.phenomenon = GWEATHER_PHENOMENON_SMALL_HAIL;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (sphen, "UP")) {
|
|
rpm-build |
ca2b01 |
new_cond.phenomenon = GWEATHER_PHENOMENON_UNKNOWN_PRECIPITATION;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (sphen, "BR")) {
|
|
rpm-build |
ca2b01 |
new_cond.phenomenon = GWEATHER_PHENOMENON_MIST;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (sphen, "FG")) {
|
|
rpm-build |
ca2b01 |
new_cond.phenomenon = GWEATHER_PHENOMENON_FOG;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (sphen, "FU")) {
|
|
rpm-build |
ca2b01 |
new_cond.phenomenon = GWEATHER_PHENOMENON_SMOKE;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (sphen, "VA")) {
|
|
rpm-build |
ca2b01 |
new_cond.phenomenon = GWEATHER_PHENOMENON_VOLCANIC_ASH;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (sphen, "SA")) {
|
|
rpm-build |
ca2b01 |
new_cond.phenomenon = GWEATHER_PHENOMENON_SAND;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (sphen, "HZ")) {
|
|
rpm-build |
ca2b01 |
new_cond.phenomenon = GWEATHER_PHENOMENON_HAZE;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (sphen, "PY")) {
|
|
rpm-build |
ca2b01 |
new_cond.phenomenon = GWEATHER_PHENOMENON_SPRAY;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (sphen, "DU")) {
|
|
rpm-build |
ca2b01 |
new_cond.phenomenon = GWEATHER_PHENOMENON_DUST;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (sphen, "SQ")) {
|
|
rpm-build |
ca2b01 |
new_cond.phenomenon = GWEATHER_PHENOMENON_SQUALL;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (sphen, "SS")) {
|
|
rpm-build |
ca2b01 |
new_cond.phenomenon = GWEATHER_PHENOMENON_SANDSTORM;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (sphen, "DS")) {
|
|
rpm-build |
ca2b01 |
new_cond.phenomenon = GWEATHER_PHENOMENON_DUSTSTORM;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (sphen, "PO")) {
|
|
rpm-build |
ca2b01 |
new_cond.phenomenon = GWEATHER_PHENOMENON_DUST_WHIRLS;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (sphen, "+FC")) {
|
|
rpm-build |
ca2b01 |
new_cond.phenomenon = GWEATHER_PHENOMENON_TORNADO;
|
|
rpm-build |
ca2b01 |
} else if (!strcmp (sphen, "FC")) {
|
|
rpm-build |
ca2b01 |
new_cond.phenomenon = GWEATHER_PHENOMENON_FUNNEL_CLOUD;
|
|
rpm-build |
ca2b01 |
} else {
|
|
rpm-build |
ca2b01 |
return;
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
if ((new_cond.qualifier != GWEATHER_QUALIFIER_NONE) || (new_cond.phenomenon != GWEATHER_PHENOMENON_NONE))
|
|
rpm-build |
ca2b01 |
new_cond.significant = TRUE;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
if (condition_more_important (&new_cond, &priv->cond))
|
|
rpm-build |
ca2b01 |
priv->cond = new_cond;
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
#define TIME_RE_STR "([0-9]{6})Z"
|
|
rpm-build |
ca2b01 |
#define WIND_RE_STR "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
|
|
rpm-build |
ca2b01 |
#define VIS_RE_STR "((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
|
|
rpm-build |
ca2b01 |
"([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
|
|
rpm-build |
ca2b01 |
"CAVOK"
|
|
rpm-build |
ca2b01 |
#define COND_RE_STR "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
|
|
rpm-build |
ca2b01 |
#define CLOUD_RE_STR "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
|
|
rpm-build |
ca2b01 |
#define TEMP_RE_STR "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
|
|
rpm-build |
ca2b01 |
#define PRES_RE_STR "(A|Q)([0-9]{4})"
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
/* POSIX regular expressions do not allow us to express "match whole words
|
|
rpm-build |
ca2b01 |
* only" in a simple way, so we have to wrap them all into
|
|
rpm-build |
ca2b01 |
* (^| )(...regex...)( |$)
|
|
rpm-build |
ca2b01 |
*/
|
|
rpm-build |
ca2b01 |
#define RE_PREFIX "(^| )("
|
|
rpm-build |
ca2b01 |
#define RE_SUFFIX ")( |$)"
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
static GRegex *metar_re[RE_NUM];
|
|
rpm-build |
ca2b01 |
static void (*metar_f[RE_NUM]) (gchar *tokp, GWeatherInfo *info);
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
static void
|
|
rpm-build |
ca2b01 |
metar_init_re (void)
|
|
rpm-build |
ca2b01 |
{
|
|
rpm-build |
ca2b01 |
static gboolean initialized = FALSE;
|
|
rpm-build |
ca2b01 |
if (initialized)
|
|
rpm-build |
ca2b01 |
return;
|
|
rpm-build |
ca2b01 |
initialized = TRUE;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
metar_re[TIME_RE] = g_regex_new (RE_PREFIX TIME_RE_STR RE_SUFFIX, G_REGEX_OPTIMIZE, 0, NULL);
|
|
rpm-build |
ca2b01 |
metar_re[WIND_RE] = g_regex_new (RE_PREFIX WIND_RE_STR RE_SUFFIX, G_REGEX_OPTIMIZE, 0, NULL);
|
|
rpm-build |
ca2b01 |
metar_re[VIS_RE] = g_regex_new (RE_PREFIX VIS_RE_STR RE_SUFFIX, G_REGEX_OPTIMIZE, 0, NULL);
|
|
rpm-build |
ca2b01 |
metar_re[COND_RE] = g_regex_new (RE_PREFIX COND_RE_STR RE_SUFFIX, G_REGEX_OPTIMIZE, 0, NULL);
|
|
rpm-build |
ca2b01 |
metar_re[CLOUD_RE] = g_regex_new (RE_PREFIX CLOUD_RE_STR RE_SUFFIX, G_REGEX_OPTIMIZE, 0, NULL);
|
|
rpm-build |
ca2b01 |
metar_re[TEMP_RE] = g_regex_new (RE_PREFIX TEMP_RE_STR RE_SUFFIX, G_REGEX_OPTIMIZE, 0, NULL);
|
|
rpm-build |
ca2b01 |
metar_re[PRES_RE] = g_regex_new (RE_PREFIX PRES_RE_STR RE_SUFFIX, G_REGEX_OPTIMIZE, 0, NULL);
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
metar_f[TIME_RE] = metar_tok_time;
|
|
rpm-build |
ca2b01 |
metar_f[WIND_RE] = metar_tok_wind;
|
|
rpm-build |
ca2b01 |
metar_f[VIS_RE] = metar_tok_vis;
|
|
rpm-build |
ca2b01 |
metar_f[COND_RE] = metar_tok_cond;
|
|
rpm-build |
ca2b01 |
metar_f[CLOUD_RE] = metar_tok_cloud;
|
|
rpm-build |
ca2b01 |
metar_f[TEMP_RE] = metar_tok_temp;
|
|
rpm-build |
ca2b01 |
metar_f[PRES_RE] = metar_tok_pres;
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
gboolean
|
|
rpm-build |
ca2b01 |
metar_parse (gchar *metar, GWeatherInfo *info)
|
|
rpm-build |
ca2b01 |
{
|
|
rpm-build |
ca2b01 |
gchar *p;
|
|
rpm-build |
ca2b01 |
//gchar *rmk;
|
|
rpm-build |
ca2b01 |
gint i, i2;
|
|
rpm-build |
ca2b01 |
gchar *tokp;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
g_return_val_if_fail (info != NULL, FALSE);
|
|
rpm-build |
ca2b01 |
g_return_val_if_fail (metar != NULL, FALSE);
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
metar_init_re ();
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
/*
|
|
rpm-build |
ca2b01 |
* Force parsing to end at "RMK" field. This prevents a subtle
|
|
rpm-build |
ca2b01 |
* problem when info within the remark happens to match an earlier state
|
|
rpm-build |
ca2b01 |
* and, as a result, throws off all the remaining expression
|
|
rpm-build |
ca2b01 |
*/
|
|
rpm-build |
ca2b01 |
if (0 != (p = strstr (metar, " RMK "))) {
|
|
rpm-build |
ca2b01 |
*p = '\0';
|
|
rpm-build |
ca2b01 |
//rmk = p + 5; // uncomment this if RMK data becomes useful
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
p = metar;
|
|
rpm-build |
ca2b01 |
i = TIME_RE;
|
|
rpm-build |
ca2b01 |
while (*p) {
|
|
rpm-build |
ca2b01 |
int token_start, token_end;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
i2 = RE_NUM;
|
|
rpm-build |
ca2b01 |
token_start = strlen(p);
|
|
rpm-build |
ca2b01 |
token_end = token_start;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
for (i = 0; i < RE_NUM; i++) {
|
|
rpm-build |
ca2b01 |
GMatchInfo *match_info;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
if (g_regex_match_full (metar_re[i], p, -1, 0, 0, &match_info, NULL))
|
|
rpm-build |
ca2b01 |
{
|
|
rpm-build |
ca2b01 |
int tmp_token_start, tmp_token_end;
|
|
rpm-build |
ca2b01 |
/* Skip leading and trailing space characters, if present.
|
|
rpm-build |
ca2b01 |
(the regular expressions include those characters to
|
|
rpm-build |
ca2b01 |
only get matches limited to whole words). */
|
|
rpm-build |
ca2b01 |
g_match_info_fetch_pos (match_info, 0, &tmp_token_start, &tmp_token_end);
|
|
rpm-build |
ca2b01 |
if (p[tmp_token_start] == ' ') tmp_token_start++;
|
|
rpm-build |
ca2b01 |
if (p[tmp_token_end - 1] == ' ') tmp_token_end--;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
/* choose the regular expression with the earliest match */
|
|
rpm-build |
ca2b01 |
if (tmp_token_start < token_start) {
|
|
rpm-build |
ca2b01 |
i2 = i;
|
|
rpm-build |
ca2b01 |
token_start = tmp_token_start;
|
|
rpm-build |
ca2b01 |
token_end = tmp_token_end;
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
g_match_info_unref (match_info);
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
if (i2 != RE_NUM) {
|
|
rpm-build |
ca2b01 |
tokp = g_strndup (p + token_start, token_end - token_start);
|
|
rpm-build |
ca2b01 |
metar_f[i2] (tokp, info);
|
|
rpm-build |
ca2b01 |
g_free (tokp);
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
p += token_end;
|
|
rpm-build |
ca2b01 |
p += strspn (p, " ");
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
return TRUE;
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
static void
|
|
rpm-build |
ca2b01 |
metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
|
|
rpm-build |
ca2b01 |
{
|
|
rpm-build |
ca2b01 |
GWeatherInfo *info = (GWeatherInfo *)data;
|
|
rpm-build |
ca2b01 |
GWeatherInfoPrivate *priv;
|
|
rpm-build |
ca2b01 |
WeatherLocation *loc;
|
|
rpm-build |
ca2b01 |
const gchar *p, *eoln;
|
|
rpm-build |
ca2b01 |
gchar *searchkey, *metar;
|
|
rpm-build |
ca2b01 |
gboolean success = FALSE;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
g_return_if_fail (info != NULL);
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
priv = info->priv;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
|
|
rpm-build |
ca2b01 |
if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code))
|
|
rpm-build |
ca2b01 |
priv->network_error = TRUE;
|
|
rpm-build |
ca2b01 |
else {
|
|
rpm-build |
ca2b01 |
if (msg->status_code != SOUP_STATUS_CANCELLED)
|
|
rpm-build |
ca2b01 |
/* Translators: %d is an error code, and %s the error string */
|
|
rpm-build |
ca2b01 |
g_warning (_("Failed to get METAR data: %d %s.\n"),
|
|
rpm-build |
ca2b01 |
msg->status_code, msg->reason_phrase);
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
_gweather_info_request_done (info, msg);
|
|
rpm-build |
ca2b01 |
return;
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
loc = &priv->location;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
|
|
rpm-build |
ca2b01 |
p = strstr (msg->response_body->data, searchkey);
|
|
rpm-build |
ca2b01 |
g_free (searchkey);
|
|
rpm-build |
ca2b01 |
if (p) {
|
|
rpm-build |
ca2b01 |
p += WEATHER_LOCATION_CODE_LEN + 2;
|
|
rpm-build |
ca2b01 |
eoln = strchr(p, '\n');
|
|
rpm-build |
ca2b01 |
if (eoln)
|
|
rpm-build |
ca2b01 |
metar = g_strndup (p, eoln - p);
|
|
rpm-build |
ca2b01 |
else
|
|
rpm-build |
ca2b01 |
metar = g_strdup (p);
|
|
rpm-build |
ca2b01 |
success = metar_parse (metar, info);
|
|
rpm-build |
ca2b01 |
g_free (metar);
|
|
rpm-build |
ca2b01 |
} else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
|
|
rpm-build |
ca2b01 |
/* The response doesn't even seem to have come from NOAA...
|
|
rpm-build |
ca2b01 |
* most likely it is a wifi hotspot login page. Call that a
|
|
rpm-build |
ca2b01 |
* network error.
|
|
rpm-build |
ca2b01 |
*/
|
|
rpm-build |
ca2b01 |
priv->network_error = TRUE;
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
priv->valid = success;
|
|
rpm-build |
ca2b01 |
_gweather_info_request_done (info, msg);
|
|
rpm-build |
ca2b01 |
}
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
/* Read current conditions and fill in info structure */
|
|
rpm-build |
ca2b01 |
void
|
|
rpm-build |
ca2b01 |
metar_start_open (GWeatherInfo *info)
|
|
rpm-build |
ca2b01 |
{
|
|
rpm-build |
ca2b01 |
GWeatherInfoPrivate *priv;
|
|
rpm-build |
ca2b01 |
WeatherLocation *loc;
|
|
rpm-build |
ca2b01 |
SoupMessage *msg;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
g_return_if_fail (info != NULL);
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
priv = info->priv;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
priv->valid = priv->network_error = FALSE;
|
|
rpm-build |
ca2b01 |
loc = &priv->location;
|
|
rpm-build |
ca2b01 |
|
|
rpm-build |
ca2b01 |
msg = soup_form_request_new (
|
|
rpm-build |
ca2b01 |
"GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
|
|
rpm-build |
ca2b01 |
"dataSource", "metars",
|
|
rpm-build |
ca2b01 |
"requestType", "retrieve",
|
|
rpm-build |
ca2b01 |
"format", "xml",
|
|
rpm-build |
ca2b01 |
"hoursBeforeNow", "3",
|
|
rpm-build |
ca2b01 |
"mostRecent", "true",
|
|
rpm-build |
ca2b01 |
"fields", "raw_text",
|
|
rpm-build |
ca2b01 |
"stationString", loc->code,
|
|
rpm-build |
ca2b01 |
NULL);
|
|
rpm-build |
ca2b01 |
_gweather_info_begin_request (info, msg);
|
|
rpm-build |
ca2b01 |
soup_session_queue_message (priv->session, msg, metar_finish, info);
|
|
rpm-build |
ca2b01 |
}
|