switched from wpitchoune@gmail.com to jeanfi@gmail.com (my usual email)
[psensor.git] / src / rsensor.c
1 /*
2     Copyright (C) 2010-2011 jeanfi@gmail.com
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU 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
20 #include <locale.h>
21 #include <libintl.h>
22 #define _(str) gettext(str)
23
24 #include "plib/url.h"
25 #include "server/server.h"
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include <curl/curl.h>
32 #include <json/json.h>
33
34 #include "rsensor.h"
35
36 struct ucontent {
37         char *data;
38         size_t len;
39 };
40
41 static CURL *curl;
42
43 size_t cbk_curl(void *buffer, size_t size, size_t nmemb, void *userp)
44 {
45         size_t realsize = size * nmemb;
46         struct ucontent *mem = (struct ucontent *)userp;
47
48         mem->data = realloc(mem->data, mem->len + realsize + 1);
49
50         memcpy(&(mem->data[mem->len]), buffer, realsize);
51         mem->len += realsize;
52         mem->data[mem->len] = 0;
53
54         return realsize;
55 }
56
57 char *create_api_1_0_sensors_url(const char *base_url)
58 {
59         char *nurl = url_normalize(base_url);
60         int n = strlen(nurl) + strlen(URL_BASE_API_1_0_SENSORS) + 1;
61         char *ret = malloc(n);
62
63         strcpy(ret, nurl);
64         strcat(ret, URL_BASE_API_1_0_SENSORS);
65
66         free(nurl);
67
68         return ret;
69 }
70
71 struct psensor *json_object_to_psensor(json_object * o,
72                                        const char *sensors_url,
73                                        int values_max_length)
74 {
75         json_object *oid;
76         json_object *oname;
77         json_object *otype;
78         struct psensor *s;
79         char *eid;
80         char *url;
81
82         oid = json_object_object_get(o, "id");
83         oname = json_object_object_get(o, "name");
84         otype = json_object_object_get(o, "type");
85
86         eid = url_encode(json_object_get_string(oid));
87         url = malloc(strlen(sensors_url) + 1 + strlen(eid) + 1);
88         sprintf(url, "%s/%s", sensors_url, eid);
89
90         s = psensor_create(strdup(url),
91                            strdup(json_object_get_string(oname)),
92                            json_object_get_int(otype) | SENSOR_TYPE_REMOTE,
93                            values_max_length);
94         s->url = url;
95
96         free(eid);
97
98         return s;
99 }
100
101 void rsensor_init()
102 {
103         curl = curl_easy_init();
104 }
105
106 void rsensor_end()
107 {
108         curl_easy_cleanup(curl);
109 }
110
111 json_object *get_json_object(const char *url)
112 {
113
114         struct ucontent chunk;
115         json_object *obj = NULL;
116
117         if (!curl)
118                 return NULL;
119
120         chunk.data = malloc(1);
121         chunk.len = 0;
122
123         curl_easy_setopt(curl, CURLOPT_URL, url);
124         curl_easy_setopt(curl, CURLOPT_VERBOSE, 0);
125         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cbk_curl);
126         curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
127
128         if (curl_easy_perform(curl) == CURLE_OK)
129                 obj = json_tokener_parse(chunk.data);
130         else
131                 fprintf(stderr, _("ERROR: Fail to connect to: %s\n"), url);
132
133         free(chunk.data);
134
135         return obj;
136 }
137
138 struct psensor **get_remote_sensors(const char *server_url,
139                                     int values_max_length)
140 {
141         struct psensor **sensors = NULL;
142         char *url;
143         json_object *obj;
144
145         url = create_api_1_0_sensors_url(server_url);
146
147         obj = get_json_object(url);
148
149         if (obj && !is_error(obj)) {
150                 int i;
151                 int n = json_object_array_length(obj);
152                 sensors = malloc((n + 1) * sizeof(struct psensor *));
153
154                 for (i = 0; i < n; i++) {
155                         struct psensor *s = json_object_to_psensor
156                             (json_object_array_get_idx(obj, i),
157                              url,
158                              values_max_length);
159                         sensors[i] = s;
160                 }
161
162                 sensors[n] = NULL;
163
164                 json_object_put(obj);
165         } else {
166                 fprintf(stderr, _("ERROR: Invalid content: %s\n"), url);
167         }
168
169         free(url);
170
171         if (!sensors) {
172                 sensors = malloc(sizeof(struct psensor *));
173                 *sensors = NULL;
174         }
175
176         return sensors;
177 }
178
179 void remote_psensor_update(struct psensor *s)
180 {
181         json_object *obj = get_json_object(s->url);
182
183         if (obj && !is_error(obj)) {
184                 json_object *om;
185
186                 om = json_object_object_get(obj, "last_measure");
187
188                 if (!is_error(obj)) {
189                         json_object *ov, *ot;
190                         struct timeval tv;
191
192                         ov = json_object_object_get(om, "value");
193                         ot = json_object_object_get(om, "time");
194
195                         tv.tv_sec = json_object_get_int(ot);
196                         tv.tv_usec = 0;
197
198                         psensor_set_current_measure
199                             (s, json_object_get_double(ov), tv);;
200                 }
201
202                 json_object_put(obj);
203         } else {
204                 printf(_("ERROR: Invalid JSON: %s\n"), s->url);
205         }
206
207 }
208
209 void remote_psensor_list_update(struct psensor **sensors)
210 {
211         struct psensor **cur = sensors;
212
213         while (*cur) {
214                 struct psensor *s = *cur;
215
216                 if (s->type & SENSOR_TYPE_REMOTE)
217                         remote_psensor_update(s);
218
219                 cur++;
220         }
221 }