Merge tag 'upstream/1.1.1'
[psensor-pkg-ubuntu.git] / src / rsensor.c
1 /*
2  * Copyright (C) 2010-2014 jeanfi@gmail.com
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301 USA
18  */
19 #include <locale.h>
20 #include <libintl.h>
21 #define _(str) gettext(str)
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include <curl/curl.h>
28
29 #include "psensor_json.h"
30 #include "rsensor.h"
31 #include "server/server.h"
32 #include "url.h"
33
34 struct ucontent {
35         char *data;
36         size_t len;
37 };
38
39 static CURL *curl;
40
41 static size_t cbk_curl(void *buffer, size_t size, size_t nmemb, void *userp)
42 {
43         size_t realsize;
44         struct ucontent *mem;
45
46         realsize = size * nmemb;
47         mem = (struct ucontent *)userp;
48
49         mem->data = realloc(mem->data, mem->len + realsize + 1);
50
51         memcpy(&(mem->data[mem->len]), buffer, realsize);
52         mem->len += realsize;
53         mem->data[mem->len] = 0;
54
55         return realsize;
56 }
57
58 static char *create_api_1_1_sensors_url(const char *base_url)
59 {
60         char *nurl, *ret;
61         int n;
62
63         nurl = url_normalize(base_url);
64         n = strlen(nurl) + strlen(URL_BASE_API_1_1_SENSORS) + 1;
65         ret = malloc(n);
66
67         strcpy(ret, nurl);
68         strcat(ret, URL_BASE_API_1_1_SENSORS);
69
70         free(nurl);
71
72         return ret;
73 }
74
75 void rsensor_init()
76 {
77         curl = curl_easy_init();
78 }
79
80 void rsensor_cleanup()
81 {
82         curl_easy_cleanup(curl);
83 }
84
85 static json_object *get_json_object(const char *url)
86 {
87         struct ucontent chunk;
88         json_object *obj;
89
90         obj = NULL;
91
92         if (!curl)
93                 return NULL;
94
95         chunk.data = malloc(1);
96         chunk.len = 0;
97
98         curl_easy_setopt(curl, CURLOPT_URL, url);
99         curl_easy_setopt(curl, CURLOPT_VERBOSE, 0);
100         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cbk_curl);
101         curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
102
103         log_debug("HTTP request %s", url);
104         if (curl_easy_perform(curl) == CURLE_OK)
105                 obj = json_tokener_parse(chunk.data);
106         else
107                 log_printf(LOG_ERR, _("Fail to connect to: %s"), url);
108
109         free(chunk.data);
110
111         return obj;
112 }
113
114 struct psensor **get_remote_sensors(const char *server_url,
115                                     int values_max_length)
116 {
117         struct psensor **sensors, *s;
118         char *url;
119         json_object *obj;
120         int i, n;
121
122         sensors = NULL;
123
124         url = create_api_1_1_sensors_url(server_url);
125
126         obj = get_json_object(url);
127
128         if (obj && !is_error(obj)) {
129                 n = json_object_array_length(obj);
130                 sensors = malloc((n + 1) * sizeof(struct psensor *));
131
132                 for (i = 0; i < n; i++) {
133                         s = psensor_new_from_json
134                                 (json_object_array_get_idx(obj, i),
135                                  url,
136                                  values_max_length);
137                         sensors[i] = s;
138                 }
139
140                 sensors[n] = NULL;
141
142                 json_object_put(obj);
143         } else {
144                 log_printf(LOG_ERR, _("Invalid content: %s"), url);
145         }
146
147         free(url);
148
149         if (!sensors) {
150                 sensors = malloc(sizeof(struct psensor *));
151                 *sensors = NULL;
152         }
153
154         return sensors;
155 }
156
157 void remote_psensor_update(struct psensor *s)
158 {
159         json_object *obj;
160
161         obj = get_json_object(s->url);
162
163         if (obj && !is_error(obj)) {
164                 json_object *om;
165
166                 json_object_object_get_ex(obj, "last_measure", &om);
167
168                 if (!is_error(obj)) {
169                         json_object *ov, *ot;
170                         struct timeval tv;
171
172                         json_object_object_get_ex(om, "value", &ov);
173                         json_object_object_get_ex(om, "time", &ot);
174
175                         tv.tv_sec = json_object_get_int(ot);
176                         tv.tv_usec = 0;
177
178                         psensor_set_current_measure
179                             (s, json_object_get_double(ov), tv);
180                 }
181
182                 json_object_put(obj);
183         } else {
184                 log_printf(LOG_ERR, _("Invalid JSON: %s"), s->url);
185         }
186
187 }
188
189 void remote_psensor_list_update(struct psensor **sensors)
190 {
191         struct psensor **cur;
192
193         cur = sensors;
194         while (*cur) {
195                 struct psensor *s = *cur;
196
197                 if (s->type & SENSOR_TYPE_REMOTE)
198                         remote_psensor_update(s);
199
200                 cur++;
201         }
202 }