aboutsummaryrefslogtreecommitdiffstats
path: root/binding/afm-weather-binding.c
diff options
context:
space:
mode:
Diffstat (limited to 'binding/afm-weather-binding.c')
-rw-r--r--binding/afm-weather-binding.c94
1 files changed, 72 insertions, 22 deletions
diff --git a/binding/afm-weather-binding.c b/binding/afm-weather-binding.c
index 1103722..4c2418d 100644
--- a/binding/afm-weather-binding.c
+++ b/binding/afm-weather-binding.c
@@ -23,6 +23,8 @@
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
+#include <glib.h>
+#include <gio/gio.h>
#include <curl/curl.h>
#include <json-c/json.h>
@@ -33,16 +35,29 @@
#define OPENWEATHER_URL "http://api.openweathermap.org/data/2.5/weather?lat=%.4f&lon=%.4f&units=imperial&APPID=%s"
struct {
- char *api_key;
- char url[128];
- char buffer[1024];
+ gchar *api_key;
+ gchar *url;
+ gchar buffer[1024];
} data;
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
static struct afb_event weather_event;
+// Forward declaration
+gboolean update_weather_data(gpointer ptr);
+
+static void *weather_loop_thread(void *ptr)
+{
+ g_timeout_add_seconds(900, update_weather_data, NULL);
+
+ g_main_loop_run(g_main_loop_new(NULL, FALSE));
+
+ return NULL;
+}
+
static int init()
{
+ pthread_t thread_id;
json_object *response, *query;
int ret;
@@ -58,7 +73,7 @@ static int init()
ret = afb_service_call_sync("persistence", "read", query, &response);
if (ret < 0) {
- data.api_key = strdup(OPENWEATHER_API_KEY);
+ data.api_key = g_strdup(OPENWEATHER_API_KEY);
AFB_WARNING("Cannot get OPENWEATHERMAP_API_KEY from persistence storage, defaulting to %s", data.api_key);
} else {
json_object *jresp = NULL;
@@ -66,7 +81,7 @@ static int init()
json_object_object_get_ex(response, "response", &jresp);
json_object_object_get_ex(jresp, "value", &jresp);
- data.api_key = strdup(json_object_get_string(jresp));
+ data.api_key = g_strdup(json_object_get_string(jresp));
AFB_NOTICE("OPENWEATHERMAP_API_KEY retrieved from persistence: %s", data.api_key);
}
@@ -92,7 +107,7 @@ static int init()
weather_event = afb_daemon_make_event("weather");
- return 0;
+ return pthread_create(&thread_id, NULL, weather_loop_thread, NULL);
}
static size_t weather_cb(char *ptr, size_t size, size_t nmemb, void *usr)
@@ -103,7 +118,7 @@ static size_t weather_cb(char *ptr, size_t size, size_t nmemb, void *usr)
if (realsize > (sizeof(data.buffer) - 1))
return -ENOMEM;
- pthread_mutex_lock(&mutex);
+ pthread_rwlock_rdlock(&rwlock);
memcpy(data.buffer, ptr, realsize);
data.buffer[realsize] = '\0';
@@ -113,16 +128,45 @@ static size_t weather_cb(char *ptr, size_t size, size_t nmemb, void *usr)
if (jresp)
json_object_object_add(jresp, "url", json_object_new_string(data.url));
- pthread_mutex_unlock(&mutex);
+ pthread_rwlock_unlock(&rwlock);
+
afb_event_push(weather_event, jresp);
return realsize;
}
+gboolean update_weather_data(gpointer ptr)
+{
+ CURL *ch;
+
+ pthread_rwlock_rdlock(&rwlock);
+
+ if (data.url == NULL) {
+ pthread_rwlock_unlock(&rwlock);
+ return TRUE;
+ }
+
+ ch = curl_easy_init();
+
+ if (ch == NULL) {
+ pthread_rwlock_unlock(&rwlock);
+ return TRUE;
+ }
+
+ curl_easy_setopt(ch, CURLOPT_URL, data.url);
+ curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, weather_cb);
+
+ (void) curl_easy_perform(ch);
+ curl_easy_cleanup(ch);
+
+ pthread_rwlock_unlock(&rwlock);
+
+ return TRUE;
+}
+
static void onevent(const char *event, struct json_object *object)
{
json_object *val = NULL;
- CURL *ch = NULL;
double latitude, longitude;
int ret;
@@ -138,31 +182,37 @@ static void onevent(const char *event, struct json_object *object)
if (!ret)
return;
longitude = json_object_get_double(val);
+ ret = 0;
- sprintf(data.url, OPENWEATHER_URL, latitude, longitude, data.api_key);
+ pthread_rwlock_wrlock(&rwlock);
- ch = curl_easy_init();
- if (ch == NULL)
- return;
+ if (data.url != NULL) {
+ g_free(data.url);
+ data.url = NULL;
+ ret = -1;
+ }
- curl_easy_setopt(ch, CURLOPT_URL, data.url);
- curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, weather_cb);
+ data.url = g_strdup_printf(OPENWEATHER_URL, latitude, longitude, data.api_key);
- (void) curl_easy_perform(ch);
- curl_easy_cleanup(ch);
+ pthread_rwlock_unlock(&rwlock);
+
+ // Initial Weather Data
+ if (data.url != NULL && !ret)
+ update_weather_data(NULL);
}
static void current_weather(struct afb_req request)
{
json_object *jresp = NULL;
- pthread_mutex_lock(&mutex);
+ pthread_rwlock_rdlock(&rwlock);
+
jresp = json_tokener_parse(data.buffer);
if (jresp)
json_object_object_add(jresp, "url", json_object_new_string(data.url));
- pthread_mutex_unlock(&mutex);
+ pthread_rwlock_unlock(&rwlock);
if (jresp == NULL) {
afb_req_fail(request, "failed", "No weather data currently");
@@ -211,8 +261,8 @@ static void api_key(struct afb_req request)
}
if (data.api_key != NULL) {
- free(data.api_key);
- data.api_key = strdup(value);
+ g_free(data.api_key);
+ data.api_key = g_strdup(value);
}
afb_req_success(request, jresp, NULL);