2
* This file is a part of the Cairo-Dock project
4
* Copyright : (C) see the 'copyright' file.
5
* E-mail : see the 'copyright' file.
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU General Public License
9
* as published by the Free Software Foundation; either version 3
10
* of the License, or (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program. If not, see <http://www.gnu.org/licenses/>.
20
/******************************************************************************
22
This file is a part of the cairo-dock program,
23
released under the terms of the GNU General Public License.
25
Written by Fabrice Rey (for any bug report, please mail me to fabounet@users.berlios.de)
27
******************************************************************************/
33
#include <libxml/tree.h>
34
#include <libxml/parser.h>
35
#include <glib/gstdio.h>
37
#include "applet-struct.h"
38
#include "applet-read-data.h"
40
#define CD_WEATHER_BASE_URL "http://xml.weather.com"
42
gchar *cd_weather_get_location_data (gchar *cLocation)
44
gchar *cLocationFilePath = g_strdup ("/tmp/weather-location.XXXXXX");
45
int fds = mkstemp (cLocationFilePath);
48
g_free (cLocationFilePath);
51
gchar *cCommand = g_strdup_printf ("wget \""CD_WEATHER_BASE_URL"/search/search?where=%s\" -O %s -o /dev/null -t 3 -T 10", cLocation, cLocationFilePath);
52
int r = system (cCommand);
55
return cLocationFilePath;
59
static xmlDocPtr _cd_weather_open_xml_file (gchar *cDataFilePath, xmlNodePtr *root_node, gchar *cRootNodeName, GError **erreur)
61
if (cairo_dock_get_file_size (cDataFilePath) == 0)
63
g_set_error (erreur, 1, 1, "file '%s' doesn't exist (no connection ?)", cDataFilePath);
68
xmlDocPtr doc = xmlParseFile (cDataFilePath);
71
g_set_error (erreur, 1, 1, "file '%s' is uncorrect (no connection ?)", cDataFilePath);
75
xmlNodePtr noeud = xmlDocGetRootElement (doc);
76
if (noeud == NULL || xmlStrcmp (noeud->name, (const xmlChar *) cRootNodeName) != 0)
78
g_set_error (erreur, 1, 2, "xml file '%s' is not well formed (weather.com may have changed its data format)", cDataFilePath);
84
static void _cd_weather_close_xml_file (xmlDocPtr doc)
91
GList *cd_weather_parse_location_data (gchar *cDataFilePath, GError **erreur)
93
cd_message ("%s (%s)", __func__, cDataFilePath);
95
GError *tmp_erreur = NULL;
97
xmlDocPtr doc = _cd_weather_open_xml_file (cDataFilePath, &noeud, "search", &tmp_erreur);
98
if (tmp_erreur != NULL)
100
g_propagate_error (erreur, tmp_erreur);
101
_cd_weather_close_xml_file (doc);
105
GList *cLocationsList = NULL;
107
for (param = noeud->xmlChildrenNode; param != NULL; param = param->next)
109
if (xmlStrcmp (param->name, (const xmlChar *) "loc") == 0)
111
cLocationsList = g_list_prepend (cLocationsList, xmlNodeGetContent (param));
112
cLocationsList = g_list_prepend (cLocationsList, xmlGetProp (param, (xmlChar *) "id"));
115
_cd_weather_close_xml_file (doc);
116
return cLocationsList;
120
static void _cd_weather_parse_data (CairoDockModuleInstance *myApplet, gchar *cDataFilePath, gboolean bParseHeader, GError **erreur)
122
cd_message ("%s (%s)", __func__, cDataFilePath);
124
GError *tmp_erreur = NULL;
126
xmlDocPtr doc = _cd_weather_open_xml_file (cDataFilePath, &noeud, "weather", &tmp_erreur);
127
if (tmp_erreur != NULL)
129
g_propagate_error (erreur, tmp_erreur);
130
_cd_weather_close_xml_file (doc);
134
xmlNodePtr param, fils, petitfils, arrpetitfils, arrarrpetitfils;
135
gchar *nom, *visible, *name, *defaultsource = NULL, *source, *where;
138
gchar *index_str, *cDayName, *cDate, *str;
139
for (param = noeud->xmlChildrenNode; param != NULL; param = param->next)
141
if (bParseHeader && xmlStrcmp (param->name, (const xmlChar *) "head") == 0)
143
for (fils = param->children; fils != NULL; fils = fils->next)
145
if (xmlStrcmp (fils->name, (const xmlChar *) "ut") == 0)
147
gchar *degree = xmlNodeGetContent (fils);
148
if (degree == NULL || strncmp (degree, "Ā°", strlen ("Ā°")) != 0)
150
myData.units.cTemp = g_strconcat ("Ā°", degree, NULL);
154
myData.units.cTemp = degree;
156
else if (xmlStrcmp (fils->name, (const xmlChar *) "ud") == 0)
157
myData.units.cDistance = xmlNodeGetContent (fils);
158
else if (xmlStrcmp (fils->name, (const xmlChar *) "us") == 0)
159
myData.units.cSpeed = xmlNodeGetContent (fils);
160
else if (xmlStrcmp (fils->name, (const xmlChar *) "up") == 0)
161
myData.units.cPressure = xmlNodeGetContent (fils);
162
//else if (xmlStrcmp (fils->name, (const xmlChar *) "ur") == 0) // ?
163
// myData.units.cR = xmlNodeGetContent (fils);
166
else if (bParseHeader && xmlStrcmp (param->name, (const xmlChar *) "loc") == 0)
168
for (fils = param->children; fils != NULL; fils = fils->next)
170
if (xmlStrcmp (fils->name, (const xmlChar *) "dnam") == 0)
171
myData.cLocation = xmlNodeGetContent (fils);
172
else if (xmlStrcmp (fils->name, (const xmlChar *) "lat") == 0)
173
myData.cLat = xmlNodeGetContent (fils);
174
else if (xmlStrcmp (fils->name, (const xmlChar *) "lon") == 0)
175
myData.cLon = xmlNodeGetContent (fils);
176
else if (xmlStrcmp (fils->name, (const xmlChar *) "sunr") == 0)
177
myData.currentConditions.cSunRise = xmlNodeGetContent (fils);
178
else if (xmlStrcmp (fils->name, (const xmlChar *) "suns") == 0)
179
myData.currentConditions.cSunSet = xmlNodeGetContent (fils);
182
else if (xmlStrcmp (param->name, (const xmlChar *) "cc") == 0)
184
for (fils = param->children; fils != NULL; fils = fils->next)
186
if (xmlStrcmp (fils->name, (const xmlChar *) "lsup") == 0)
187
myData.currentConditions.cDataAcquisitionDate = xmlNodeGetContent (fils);
188
else if (xmlStrcmp (fils->name, (const xmlChar *) "obst") == 0)
189
myData.currentConditions.cObservatory = xmlNodeGetContent (fils);
190
else if (xmlStrcmp (fils->name, (const xmlChar *) "tmp") == 0)
191
myData.currentConditions.cTemp = xmlNodeGetContent (fils);
192
else if (xmlStrcmp (fils->name, (const xmlChar *) "flik") == 0)
193
myData.currentConditions.cFeeledTemp = xmlNodeGetContent (fils);
194
else if (xmlStrcmp (fils->name, (const xmlChar *) "t") == 0)
195
myData.currentConditions.cWeatherDescription = xmlNodeGetContent (fils);
196
else if (xmlStrcmp (fils->name, (const xmlChar *) "icon") == 0)
197
myData.currentConditions.cIconNumber = xmlNodeGetContent (fils);
198
else if (xmlStrcmp (fils->name, (const xmlChar *) "wind") == 0)
200
for (petitfils = fils->children; petitfils != NULL; petitfils = petitfils->next)
202
if (xmlStrcmp (petitfils->name, (const xmlChar *) "s") == 0)
203
myData.currentConditions.cWindSpeed = xmlNodeGetContent (petitfils);
204
else if (xmlStrcmp (petitfils->name, (const xmlChar *) "t") == 0)
205
myData.currentConditions.cWindDirection = xmlNodeGetContent (petitfils);
208
else if (xmlStrcmp (fils->name, (const xmlChar *) "bar") == 0)
210
for (petitfils = fils->children; petitfils != NULL; petitfils = petitfils->next)
212
if (xmlStrcmp (petitfils->name, (const xmlChar *) "r") == 0)
213
myData.currentConditions.cPressure = xmlNodeGetContent (petitfils);
216
else if (xmlStrcmp (fils->name, (const xmlChar *) "hmid") == 0)
217
myData.currentConditions.cHumidity = xmlNodeGetContent (fils);
218
else if (xmlStrcmp (fils->name, (const xmlChar *) "moon") == 0)
220
for (petitfils = fils->children; petitfils != NULL; petitfils = petitfils->next)
222
if (xmlStrcmp (petitfils->name, (const xmlChar *) "icon") == 0)
223
myData.currentConditions.cMoonIconNumber = xmlNodeGetContent (petitfils);
228
else if (xmlStrcmp (param->name, (const xmlChar *) "dayf") == 0)
230
for (fils = param->children; fils != NULL; fils = fils->next)
232
if (xmlStrcmp (fils->name, (const xmlChar *) "lsup") == 0)
233
myData.currentConditions.cDataAcquisitionDate = xmlNodeGetContent (fils);
234
else if (xmlStrcmp (fils->name, (const xmlChar *) "day") == 0)
236
index_str = (gchar *) xmlGetProp (fils, (xmlChar *) "d");
237
if (index_str == NULL)
239
i = atoi (index_str);
241
cDayName = (gchar *) xmlGetProp (fils, (xmlChar *) "t");
242
myData.days[i].cName = g_strdup (D_(cDayName));
244
cDate = (gchar *) xmlGetProp (fils, (xmlChar *) "dt");
245
str = strchr (cDate, ' ');
249
myData.days[i].cDate = g_strconcat (D_(cDate), " ", str+1, NULL);
253
myData.days[i].cDate = cDate;
254
for (petitfils = fils->children; petitfils != NULL; petitfils = petitfils->next)
256
if (xmlStrcmp (petitfils->name, (const xmlChar *) "hi") == 0)
257
myData.days[i].cTempMax = xmlNodeGetContent (petitfils);
258
else if (xmlStrcmp (petitfils->name, (const xmlChar *) "low") == 0)
259
myData.days[i].cTempMin = xmlNodeGetContent (petitfils);
260
else if (xmlStrcmp (petitfils->name, (const xmlChar *) "sunr") == 0)
261
myData.days[i].cSunRise = xmlNodeGetContent (petitfils);
262
else if (xmlStrcmp (petitfils->name, (const xmlChar *) "suns") == 0)
263
myData.days[i].cSunSet = xmlNodeGetContent (petitfils);
264
else if (xmlStrcmp (petitfils->name, (const xmlChar *) "part") == 0)
266
index_str = (gchar *) xmlGetProp (petitfils, (xmlChar *) "p");
267
if (index_str == NULL)
269
j = (*index_str == 'd' ? 0 : 1); // jour : 0 / nuit : 1.
270
for (arrpetitfils = petitfils->children; arrpetitfils != NULL; arrpetitfils = arrpetitfils->next)
272
if (xmlStrcmp (arrpetitfils->name, (const xmlChar *) "icon") == 0)
273
myData.days[i].part[j].cIconNumber = xmlNodeGetContent (arrpetitfils);
274
else if (xmlStrcmp (arrpetitfils->name, (const xmlChar *) "t") == 0)
275
myData.days[i].part[j].cWeatherDescription = xmlNodeGetContent (arrpetitfils);
276
else if (xmlStrcmp (arrpetitfils->name, (const xmlChar *) "wind") == 0)
278
for (arrarrpetitfils = arrpetitfils->children; arrarrpetitfils != NULL; arrarrpetitfils = arrarrpetitfils->next)
280
if (xmlStrcmp (arrarrpetitfils->name, (const xmlChar *) "s") == 0)
281
myData.days[i].part[j].cWindSpeed = xmlNodeGetContent (arrarrpetitfils);
282
else if (xmlStrcmp (arrarrpetitfils->name, (const xmlChar *) "t") == 0)
283
myData.days[i].part[j].cWindDirection = xmlNodeGetContent (arrarrpetitfils);
286
else if (xmlStrcmp (arrpetitfils->name, (const xmlChar *) "hmid") == 0)
287
myData.days[i].part[j].cHumidity = xmlNodeGetContent (arrpetitfils);
288
else if (xmlStrcmp (arrpetitfils->name, (const xmlChar *) "ppcp") == 0)
289
myData.days[i].part[j].cPrecipitationProba = xmlNodeGetContent (arrpetitfils);
297
_cd_weather_close_xml_file (doc);
301
void cd_weather_get_distant_data (CairoDockModuleInstance *myApplet)
303
//\____________________ On recupere les conditions courantes sur le serveur.
306
gchar *cCCDataFilePath = NULL;
307
if (myConfig.bCurrentConditions)
309
cCCDataFilePath = g_strdup ("/tmp/weather-cc.XXXXXX");
310
int fds = mkstemp (cCCDataFilePath);
313
g_free (cCCDataFilePath);
316
cCommand = g_strdup_printf ("wget \""CD_WEATHER_BASE_URL"/weather/local/%s?cc=*%s\" -O %s -o /dev/null -t 3 -T 10", myConfig.cLocationCode, (myConfig.bISUnits ? "&unit=m" : ""), cCCDataFilePath); // &prod=xoap&par=1048871467&key=12daac2f3a67cb39
317
cd_debug ("weather : %s", cCommand);
318
r = system (cCommand);
323
//\____________________ On recupere les previsions a N jours sur le serveur.
324
gchar *cForecastDataFilePath = NULL;
325
if (myConfig.iNbDays > 0)
327
cForecastDataFilePath = g_strdup ("/tmp/weather-forecast.XXXXXX");
328
int fds = mkstemp (cForecastDataFilePath);
331
g_free (cForecastDataFilePath);
334
cCommand = g_strdup_printf ("wget \""CD_WEATHER_BASE_URL"/weather/local/%s?dayf=%d%s\" -O %s -o /dev/null -t 3 -T 10", myConfig.cLocationCode, myConfig.iNbDays, (myConfig.bISUnits ? "&unit=m" : ""), cForecastDataFilePath); // &prod=xoap&par=1048871467&key=12daac2f3a67cb39
335
cd_debug ("weather : %s", cCommand);
336
r = system (cCommand);
341
//\____________________ On extrait les donnees des conditions courantes.
342
GError *erreur = NULL;
343
if (cCCDataFilePath != NULL)
345
_cd_weather_parse_data (myApplet, cCCDataFilePath, TRUE, &erreur);
348
cd_warning ("weather : %s", erreur->message);
349
g_error_free (erreur);
351
myData.bErrorInThread = TRUE;
354
myData.bErrorInThread = FALSE;
355
g_remove (cCCDataFilePath);
356
g_free (cCCDataFilePath);
359
//\____________________ On extrait les donnees des previsions a N jours.
360
if (cForecastDataFilePath != NULL)
362
_cd_weather_parse_data (myApplet, cForecastDataFilePath, FALSE, &erreur);
365
cd_warning ("weather : %s", erreur->message);
366
g_error_free (erreur);
368
myData.bErrorInThread = TRUE;
371
myData.bErrorInThread = FALSE;
372
g_remove (cForecastDataFilePath);
373
g_free (cForecastDataFilePath);