vzlogger/src/api.c

166 lines
4.7 KiB
C

/**
* Implementation of volkszaehler.org API calls
*
* @author Steffen Vogel <info@steffenvogel.de>
* @copyright Copyright (c) 2011, The volkszaehler.org project
* @package vzlogger
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*/
/*
* This file is part of volkzaehler.org
*
* volkzaehler.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* volkzaehler.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with volkszaehler.org. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include "meter.h"
#include "api.h"
#include "vzlogger.h"
extern config_options_t options;
int curl_custom_debug_callback(CURL *curl, curl_infotype type, char *data, size_t size, void *arg) {
channel_t *ch = (channel_t *) arg;
char *end = strchr(data, '\n');
if (data == end) return 0; /* skip empty line */
switch (type) {
case CURLINFO_TEXT:
case CURLINFO_END:
if (end) *end = '\0'; /* terminate without \n */
print(log_debug+5, "CURL: %.*s", ch, (int) size, data);
break;
case CURLINFO_SSL_DATA_IN:
case CURLINFO_DATA_IN:
print(log_debug+5, "CURL: Received %lu bytes", ch, (unsigned long) size);
break;
case CURLINFO_SSL_DATA_OUT:
case CURLINFO_DATA_OUT:
print(log_debug+5, "CURL: Sent %lu bytes.. ", ch, (unsigned long) size);
break;
case CURLINFO_HEADER_IN:
case CURLINFO_HEADER_OUT:
break;
}
return 0;
}
size_t curl_custom_write_callback(void *ptr, size_t size, size_t nmemb, void *data) {
size_t realsize = size * nmemb;
CURLresponse *response = (CURLresponse *) data;
response->data = realloc(response->data, response->size + realsize + 1);
if (response->data == NULL) { /* out of memory! */
print(log_error, "Cannot allocate memory", NULL);
exit(EXIT_FAILURE);
}
memcpy(&(response->data[response->size]), ptr, realsize);
response->size += realsize;
response->data[response->size] = 0;
return realsize;
}
json_object * api_json_tuples(buffer_t *buf, reading_t *first, reading_t *last) {
json_object *json_tuples = json_object_new_array();
reading_t *it;
for (it = first; it != NULL && it != last->next; it = it->next) {
struct json_object *json_tuple = json_object_new_array();
pthread_mutex_lock(&buf->mutex);
// TODO use long int of new json-c version
// API requires milliseconds => * 1000
double timestamp = tvtod(it->time) * 1000;
double value = it->value;
pthread_mutex_unlock(&buf->mutex);
json_object_array_add(json_tuple, json_object_new_double(timestamp));
json_object_array_add(json_tuple, json_object_new_double(value));
json_object_array_add(json_tuples, json_tuple);
}
return json_tuples;
}
CURL * api_curl_init(channel_t *ch) {
CURL *curl;
struct curl_slist *header = NULL;
char url[255], agent[255];
/* prepare header, uuid & url */
sprintf(agent, "User-Agent: %s/%s (%s)", PACKAGE, VERSION, curl_version()); /* build user agent */
sprintf(url, "%s/data/%s.json", ch->middleware, ch->uuid); /* build url */
header = curl_slist_append(header, "Content-type: application/json");
header = curl_slist_append(header, "Accept: application/json");
header = curl_slist_append(header, agent);
curl = curl_easy_init();
if (!curl) {
print(log_error, "CURL: cannot create handle", ch);
exit(EXIT_FAILURE);
}
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
curl_easy_setopt(curl, CURLOPT_VERBOSE, options.verbosity);
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, curl_custom_debug_callback);
curl_easy_setopt(curl, CURLOPT_DEBUGDATA, (void *) ch);
return curl;
}
void api_parse_exception(CURLresponse response, char *err, size_t n) {
struct json_tokener *json_tok;
struct json_object *json_obj;
json_tok = json_tokener_new();
json_obj = json_tokener_parse_ex(json_tok, response.data, response.size);
if (json_tok->err == json_tokener_success) {
json_obj = json_object_object_get(json_obj, "exception");
if (json_obj) {
snprintf(err, n, "%s: %s",
json_object_get_string(json_object_object_get(json_obj, "type")),
json_object_get_string(json_object_object_get(json_obj, "message"))
);
}
else {
strncpy(err, "missing exception", n);
}
}
else {
strncpy(err, json_tokener_errors[json_tok->err], n);
}
json_object_put(json_obj);
json_tokener_free(json_tok);
}