Compare commits
No commits in common. "master" and "0.3.3-rc1" have entirely different histories.
30 changed files with 133 additions and 313 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,7 +1,8 @@
|
|||
*~
|
||||
|
||||
# Binaries
|
||||
/src/vzlogger
|
||||
/bin/logger/vzlogger
|
||||
/bin/reader/reader
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
|
|
2
debian/changelog
vendored
2
debian/changelog
vendored
|
@ -1,4 +1,4 @@
|
|||
vzlogger (0.3.3-1) stable; urgency=low
|
||||
vzlogger (0.3.3-rc1) stable; urgency=low
|
||||
|
||||
* added support for new fluksometer
|
||||
* some code refactoring & cleanup
|
||||
|
|
|
@ -39,13 +39,7 @@ typedef struct {
|
|||
size_t size;
|
||||
} CURLresponse;
|
||||
|
||||
typedef struct {
|
||||
CURL *curl;
|
||||
struct curl_slist *headers;
|
||||
} api_handle_t;
|
||||
|
||||
int api_init(channel_t *ch, api_handle_t *api);
|
||||
void api_free(api_handle_t *api);
|
||||
CURL * api_curl_init(channel_t *ch);
|
||||
|
||||
/**
|
||||
* Reformat CURLs debugging output
|
||||
|
@ -67,6 +61,6 @@ json_object * api_json_tuples(buffer_t *buf, reading_t *first, reading_t *last);
|
|||
/**
|
||||
* Parses JSON encoded exception and stores describtion in err
|
||||
*/
|
||||
int api_parse_exception(CURLresponse response, char *err, size_t n);
|
||||
void api_parse_exception(CURLresponse response, char *err, size_t n);
|
||||
|
||||
#endif /* _API_H_ */
|
||||
|
|
|
@ -50,7 +50,7 @@ reading_t * buffer_push(buffer_t *buf, reading_t *rd);
|
|||
void buffer_free(buffer_t *buf);
|
||||
void buffer_clean(buffer_t *buf);
|
||||
void buffer_clear(buffer_t *buf);
|
||||
char * buffer_dump(buffer_t *buf, char *dump, size_t len);
|
||||
char * buffer_dump(buffer_t *buf, char *dump, int len);
|
||||
|
||||
|
||||
#endif /* _BUFFER_H_ */
|
||||
|
|
|
@ -41,6 +41,7 @@ typedef struct channel {
|
|||
|
||||
pthread_cond_t condition; /* pthread syncronization to notify logging thread and local webserver */
|
||||
pthread_t thread; /* pthread for asynchronus logging */
|
||||
pthread_status_t status; /* status of thread */
|
||||
|
||||
char *middleware; /* url to middleware */
|
||||
char *uuid; /* unique identifier for middleware */
|
||||
|
|
|
@ -91,7 +91,6 @@ typedef struct {
|
|||
|
||||
/* function pointers */
|
||||
int (*init_func)(meter_t *mtr, list_t options);
|
||||
void (*free_func)(meter_t *mtr);
|
||||
int (*open_func)(meter_t *mtr);
|
||||
int (*close_func)(meter_t *mtr);
|
||||
size_t (*read_func)(meter_t *mtr, reading_t *rds, size_t n);
|
||||
|
|
|
@ -47,7 +47,6 @@ struct meter;
|
|||
struct reading;
|
||||
|
||||
int meter_init_d0(struct meter *mtr, list_t options);
|
||||
void meter_free_d0(struct meter *mtr);
|
||||
int meter_open_d0(struct meter *mtr);
|
||||
int meter_close_d0(struct meter *mtr);
|
||||
size_t meter_read_d0(struct meter *mtr, struct reading *rds, size_t n);
|
||||
|
@ -61,6 +60,4 @@ size_t meter_read_d0(struct meter *mtr, struct reading *rds, size_t n);
|
|||
*/
|
||||
int meter_d0_open_socket(const char *node, const char *service);
|
||||
|
||||
int meter_d0_open_device(const char *device, struct termios *old_tio, speed_t baudrate);
|
||||
|
||||
#endif /* _D0_H_ */
|
||||
|
|
|
@ -38,7 +38,6 @@ struct meter;
|
|||
struct reading;
|
||||
|
||||
int meter_init_exec(struct meter *mtr, list_t options);
|
||||
void meter_free_exec(struct meter *mtr);
|
||||
int meter_open_exec(struct meter *mtr);
|
||||
int meter_close_exec(struct meter *mtr);
|
||||
size_t meter_read_exec(struct meter *mtr, struct reading *rds, size_t n);
|
||||
|
|
|
@ -41,7 +41,6 @@ struct meter;
|
|||
struct reading;
|
||||
|
||||
int meter_init_file(struct meter *mtr, list_t options);
|
||||
void meter_free_file(struct meter *mtr);
|
||||
int meter_open_file(struct meter *mtr);
|
||||
int meter_close_file(struct meter *mtr);
|
||||
size_t meter_read_file(struct meter *mtr, struct reading *rds, size_t n);
|
||||
|
|
|
@ -26,8 +26,6 @@
|
|||
#ifndef _FLUKSOV2_H_
|
||||
#define _FLUKSOV2_H_
|
||||
|
||||
#define FLUKSOV2_DEFAULT_FIFO "/var/run/spid/delta/out"
|
||||
|
||||
typedef struct {
|
||||
char *fifo;
|
||||
|
||||
|
@ -39,7 +37,6 @@ struct meter;
|
|||
struct reading;
|
||||
|
||||
int meter_init_fluksov2(struct meter *mtr, list_t options);
|
||||
void meter_free_fluksov2(struct meter *mtr);
|
||||
int meter_open_fluksov2(struct meter *mtr);
|
||||
int meter_close_fluksov2(struct meter *mtr);
|
||||
size_t meter_read_fluksov2(struct meter *mtr, struct reading *rds, size_t n);
|
||||
|
|
|
@ -38,7 +38,6 @@ struct reading;
|
|||
double ltqnorm(double p);
|
||||
|
||||
int meter_init_random(struct meter *mtr, list_t options);
|
||||
void meter_free_random(struct meter *mtr);
|
||||
int meter_open_random(struct meter *mtr);
|
||||
int meter_close_random(struct meter *mtr);
|
||||
size_t meter_read_random(struct meter *mtr, struct reading *rds, size_t n);
|
||||
|
|
|
@ -41,7 +41,6 @@ struct meter;
|
|||
struct reading;
|
||||
|
||||
int meter_init_s0(struct meter *mtr, list_t options);
|
||||
void meter_free_s0(struct meter *mtr);
|
||||
int meter_open_s0(struct meter *mtr);
|
||||
int meter_close_s0(struct meter *mtr);
|
||||
size_t meter_read_s0(struct meter *mtr, struct reading *rds, size_t n);
|
||||
|
|
|
@ -61,13 +61,6 @@ struct reading;
|
|||
*/
|
||||
int meter_init_sml(struct meter *mtr, list_t options);
|
||||
|
||||
/**
|
||||
* Freeing allocated resources during initialization
|
||||
*
|
||||
* @param mtr the meter structure
|
||||
*/
|
||||
void meter_free_sml(struct meter *mtr);
|
||||
|
||||
/**
|
||||
* Open connection via serial port or socket to meter
|
||||
*
|
||||
|
|
|
@ -51,20 +51,12 @@ typedef struct reading {
|
|||
|
||||
enum meter_procotol; /* forward declaration */
|
||||
|
||||
/**
|
||||
* Manages memory for string identifiers
|
||||
*
|
||||
* @param str string to lookup in the registry
|
||||
* @return pointer to string in the regstry
|
||||
*/
|
||||
char * reading_id_registry(const char *str);
|
||||
|
||||
/**
|
||||
* Parse two reading identifiers in a given protocol context
|
||||
*
|
||||
* @return result like in strcmp()
|
||||
*/
|
||||
int reading_id_compare(enum meter_procotol prot, reading_id_t a, reading_id_t b);
|
||||
int meter_id_compare(enum meter_procotol, reading_id_t a, reading_id_t b);
|
||||
|
||||
/**
|
||||
* Parse identifier by a given string and protocol
|
||||
|
|
|
@ -35,6 +35,14 @@
|
|||
#include "common.h"
|
||||
#include "list.h"
|
||||
|
||||
/* enumerations */
|
||||
typedef enum {
|
||||
status_unknown,
|
||||
status_running,
|
||||
status_terminated,
|
||||
status__cancelled
|
||||
} pthread_status_t;
|
||||
|
||||
/**
|
||||
* Type for mapping channels to meters
|
||||
*/
|
||||
|
@ -43,6 +51,7 @@ typedef struct map {
|
|||
list_t channels;
|
||||
|
||||
pthread_t thread;
|
||||
pthread_status_t status;
|
||||
} map_t;
|
||||
|
||||
/* prototypes */
|
||||
|
|
64
src/api.c
64
src/api.c
|
@ -107,65 +107,59 @@ json_object * api_json_tuples(buffer_t *buf, reading_t *first, reading_t *last)
|
|||
return json_tuples;
|
||||
}
|
||||
|
||||
int api_init(channel_t *ch, api_handle_t *api) {
|
||||
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 */
|
||||
|
||||
api->headers = NULL;
|
||||
api->headers = curl_slist_append(api->headers, "Content-type: application/json");
|
||||
api->headers = curl_slist_append(api->headers, "Accept: application/json");
|
||||
api->headers = curl_slist_append(api->headers, agent);
|
||||
header = curl_slist_append(header, "Content-type: application/json");
|
||||
header = curl_slist_append(header, "Accept: application/json");
|
||||
header = curl_slist_append(header, agent);
|
||||
|
||||
api->curl = curl_easy_init();
|
||||
if (!api->curl) {
|
||||
return EXIT_FAILURE;
|
||||
curl = curl_easy_init();
|
||||
if (!curl) {
|
||||
print(log_error, "CURL: cannot create handle", ch);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
curl_easy_setopt(api->curl, CURLOPT_URL, url);
|
||||
curl_easy_setopt(api->curl, CURLOPT_HTTPHEADER, api->headers);
|
||||
curl_easy_setopt(api->curl, CURLOPT_VERBOSE, options.verbosity);
|
||||
curl_easy_setopt(api->curl, CURLOPT_DEBUGFUNCTION, curl_custom_debug_callback);
|
||||
curl_easy_setopt(api->curl, CURLOPT_DEBUGDATA, (void *) ch);
|
||||
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 EXIT_SUCCESS;
|
||||
return curl;
|
||||
}
|
||||
|
||||
void api_free(api_handle_t *api) {
|
||||
curl_easy_cleanup(api->curl);
|
||||
curl_slist_free_all(api->headers);
|
||||
}
|
||||
|
||||
int api_parse_exception(CURLresponse response, char *err, size_t n) {
|
||||
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_tokener_free(json_tok);
|
||||
return ERR;
|
||||
}
|
||||
if (json_tok->err == json_tokener_success) {
|
||||
json_obj = json_object_object_get(json_obj, "exception");
|
||||
|
||||
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"))
|
||||
);
|
||||
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 {
|
||||
json_object_put(json_obj);
|
||||
json_tokener_free(json_tok);
|
||||
return ERR;
|
||||
strncpy(err, json_tokener_errors[json_tok->err], n);
|
||||
}
|
||||
|
||||
json_object_put(json_obj);
|
||||
json_tokener_free(json_tok);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
|
32
src/buffer.c
32
src/buffer.c
|
@ -97,32 +97,26 @@ void buffer_clean(buffer_t *buf) {
|
|||
pthread_mutex_unlock(&buf->mutex);
|
||||
}
|
||||
|
||||
char * buffer_dump(buffer_t *buf, char *dump, size_t len) {
|
||||
size_t pos = 0;
|
||||
dump[pos++] = '{';
|
||||
char * buffer_dump(buffer_t *buf, char *dump, int len) {
|
||||
strcpy(dump, "|");
|
||||
|
||||
for (reading_t *rd = buf->head; rd != NULL; rd = rd->next) {
|
||||
if (pos < len) {
|
||||
pos += snprintf(dump+pos, len-pos, "%.2f", rd->value);
|
||||
}
|
||||
char tmp[16];
|
||||
sprintf(tmp, "%.2f|", rd->value);
|
||||
|
||||
/* indicate last sent reading */
|
||||
if (pos < len && buf->sent == rd) {
|
||||
dump[pos++] = '!';
|
||||
}
|
||||
if (strlen(dump)+strlen(tmp) < len) {
|
||||
if (buf->sent == rd) { /* indicate last sent reading */
|
||||
strcat(dump, "!");
|
||||
}
|
||||
|
||||
/* add seperator between values */
|
||||
if (pos < len && rd->next != NULL) {
|
||||
dump[pos++] = ',';
|
||||
strcat(dump, tmp);
|
||||
}
|
||||
else {
|
||||
return NULL; /* dump buffer is full! */
|
||||
}
|
||||
}
|
||||
|
||||
if (pos+1 < len) {
|
||||
dump[pos++] = '}';
|
||||
dump[pos] = '\0'; /* zero terminated string */
|
||||
}
|
||||
|
||||
return (pos < len) ? dump : NULL; /* buffer full? */
|
||||
return dump;
|
||||
}
|
||||
|
||||
void buffer_free(buffer_t *buf) {
|
||||
|
|
|
@ -35,6 +35,7 @@ void channel_init(channel_t *ch, const char *uuid, const char *middleware, readi
|
|||
snprintf(ch->id, 5, "ch%i", instances++);
|
||||
|
||||
ch->identifier = identifier;
|
||||
ch->status = status_unknown;
|
||||
|
||||
ch->uuid = strdup(uuid);
|
||||
ch->middleware = strdup(middleware);
|
||||
|
|
37
src/meter.c
37
src/meter.c
|
@ -29,19 +29,19 @@
|
|||
#include "meter.h"
|
||||
#include "options.h"
|
||||
|
||||
#define METER_DETAIL(NAME, DESC, MAX_RDS, PERIODIC) { meter_protocol_##NAME, #NAME, DESC, MAX_RDS, PERIODIC, meter_init_##NAME, meter_free_##NAME, meter_open_##NAME, meter_close_##NAME, meter_read_##NAME }
|
||||
#define METER_DETAIL(NAME, DESC, MAX_RDS, PERIODIC) { meter_protocol_##NAME, #NAME, DESC, MAX_RDS, PERIODIC, meter_init_##NAME, meter_open_##NAME, meter_close_##NAME, meter_read_##NAME }
|
||||
|
||||
static const meter_details_t protocols[] = {
|
||||
/* alias description max_rds periodic
|
||||
===============================================================================================*/
|
||||
METER_DETAIL(file, "Read from file or fifo", 32, TRUE),
|
||||
//METER_DETAIL(exec, "Parse program output", 32, TRUE),
|
||||
METER_DETAIL(random, "Generate random values with a random walk", 1, TRUE),
|
||||
METER_DETAIL(fluksov2, "Read from Flukso's onboard SPI fifo", 16, FALSE),
|
||||
METER_DETAIL(s0, "S0-meter directly connected to RS232", 1, TRUE),
|
||||
METER_DETAIL(d0, "DLMS/IEC 62056-21 plaintext protocol", 32, FALSE),
|
||||
METER_DETAIL(file, "Read from file (ex. 1-Wire sensors via OWFS)", 32, TRUE),
|
||||
//METER_DETAIL(exec, "Read from program (ex. 1-Wire sensors via digitemp)", 32, TRUE),
|
||||
METER_DETAIL(random, "Random walk", 1, TRUE),
|
||||
METER_DETAIL(fluksov2, "Read from onboard SPI of a Flukso v2", 16, FALSE),
|
||||
METER_DETAIL(s0, "S0 on RS232", 1, TRUE),
|
||||
METER_DETAIL(d0, "Plaintext protocol (DIN EN 62056-21)", 32, FALSE),
|
||||
#ifdef SML_SUPPORT
|
||||
METER_DETAIL(sml, "Smart Message Language as used by EDL-21, eHz and SyM²", 32, FALSE),
|
||||
METER_DETAIL(sml, "Smart Meter Language", 32, FALSE),
|
||||
#endif /* SML_SUPPORT */
|
||||
{} /* stop condition for iterator */
|
||||
};
|
||||
|
@ -77,9 +77,14 @@ int meter_init(meter_t *mtr, list_t options) {
|
|||
return details->init_func(mtr, options);
|
||||
}
|
||||
|
||||
void meter_free(meter_t *mtr) {
|
||||
const meter_details_t *details = meter_get_details(mtr->protocol);
|
||||
return details->free_func(mtr);
|
||||
int meter_lookup_protocol(const char* name, meter_protocol_t *protocol) {
|
||||
for (const meter_details_t *it = meter_get_protocols(); it != NULL; it++) {
|
||||
if (strcmp(it->name, name) == 0) {
|
||||
*protocol = it->id;
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
return ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
int meter_open(meter_t *mtr) {
|
||||
|
@ -97,16 +102,6 @@ size_t meter_read(meter_t *mtr, reading_t rds[], size_t n) {
|
|||
return details->read_func(mtr, rds, n);
|
||||
}
|
||||
|
||||
int meter_lookup_protocol(const char* name, meter_protocol_t *protocol) {
|
||||
for (const meter_details_t *it = meter_get_protocols(); it != NULL; it++) {
|
||||
if (strcmp(it->name, name) == 0) {
|
||||
*protocol = it->id;
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
return ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
const meter_details_t * meter_get_protocols() {
|
||||
return protocols;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
/* socket */
|
||||
#include <netdb.h>
|
||||
|
@ -99,23 +98,12 @@ int meter_init_d0(meter_t *mtr, list_t options) {
|
|||
return SUCCESS;
|
||||
}
|
||||
|
||||
void meter_free_d0(meter_t *mtr) {
|
||||
meter_handle_d0_t *handle = &mtr->handle.d0;
|
||||
|
||||
if (handle->device != NULL) {
|
||||
free(handle->device);
|
||||
}
|
||||
|
||||
if (handle->host != NULL) {
|
||||
free(handle->host);
|
||||
}
|
||||
}
|
||||
|
||||
int meter_open_d0(meter_t *mtr) {
|
||||
meter_handle_d0_t *handle = &mtr->handle.d0;
|
||||
|
||||
if (handle->device != NULL) {
|
||||
handle->fd = meter_d0_open_device(handle->device, &handle->oldtio, handle->baudrate);
|
||||
print(log_error, "TODO: implement serial interface", mtr);
|
||||
return ERR;
|
||||
}
|
||||
else if (handle->host != NULL) {
|
||||
char *addr = strdup(handle->host);
|
||||
|
@ -304,35 +292,3 @@ int meter_d0_open_socket(const char *node, const char *service) {
|
|||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int meter_d0_open_device(const char *device, struct termios *old_tio, speed_t baudrate) {
|
||||
struct termios tio;
|
||||
memset(&tio, 0, sizeof(struct termios));
|
||||
|
||||
int fd = open(device, O_RDWR);
|
||||
if (fd < 0) {
|
||||
print(log_error, "open(%s): %s", NULL, device, strerror(errno));
|
||||
return ERR;
|
||||
}
|
||||
|
||||
/* get old configuration */
|
||||
tcgetattr(fd, &tio) ;
|
||||
|
||||
/* backup old configuration to restore it when closing the meter connection */
|
||||
memcpy(old_tio, &tio, sizeof(struct termios));
|
||||
|
||||
/* set 7-N-1 */
|
||||
tio.c_iflag &= ~(BRKINT | INLCR | IMAXBEL);
|
||||
tio.c_oflag &= ~(OPOST | ONLCR);
|
||||
tio.c_lflag &= ~(ISIG | ICANON | IEXTEN | ECHO);
|
||||
tio.c_cflag |= (CS7 | PARENB);
|
||||
|
||||
/* set baudrate */
|
||||
cfsetispeed(&tio, baudrate);
|
||||
cfsetospeed(&tio, baudrate);
|
||||
|
||||
/* apply new configuration */
|
||||
tcsetattr(fd, TCSANOW, &tio);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
|
|
@ -62,16 +62,6 @@ int meter_init_exec(meter_t *mtr, list_t options) {
|
|||
return SUCCESS;
|
||||
}
|
||||
|
||||
void meter_free_exec(meter_t *mtr) {
|
||||
meter_handle_exec_t *handle = &mtr->handle.exec;
|
||||
|
||||
free(handle->command);
|
||||
|
||||
if (handle->format != NULL) {
|
||||
free(handle->format);
|
||||
}
|
||||
}
|
||||
|
||||
int meter_open_exec(meter_t *mtr) {
|
||||
//meter_handle_exec_t *handle = &mtr->handle.exec;
|
||||
|
||||
|
|
|
@ -126,16 +126,6 @@ int meter_init_file(meter_t *mtr, list_t options) {
|
|||
return SUCCESS;
|
||||
}
|
||||
|
||||
void meter_free_file(meter_t *mtr) {
|
||||
meter_handle_file_t *handle = &mtr->handle.file;
|
||||
|
||||
free(handle->path);
|
||||
|
||||
if (handle->format != NULL) {
|
||||
free(handle->format);
|
||||
}
|
||||
}
|
||||
|
||||
int meter_open_file(meter_t *mtr) {
|
||||
meter_handle_file_t *handle = &mtr->handle.file;
|
||||
|
||||
|
|
|
@ -41,18 +41,12 @@ int meter_init_fluksov2(meter_t *mtr, list_t options) {
|
|||
handle->fifo = strdup(fifo);
|
||||
}
|
||||
else {
|
||||
handle->fifo = strdup(FLUKSOV2_DEFAULT_FIFO); /* use default path */
|
||||
handle->fifo = "/var/run/spid/delta/out"; /* use default path */
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void meter_free_fluksov2(meter_t *mtr) {
|
||||
meter_handle_fluksov2_t *handle = &mtr->handle.fluksov2;
|
||||
|
||||
free(handle->fifo);
|
||||
}
|
||||
|
||||
int meter_open_fluksov2(meter_t *mtr) {
|
||||
meter_handle_fluksov2_t *handle = &mtr->handle.fluksov2;
|
||||
|
||||
|
|
|
@ -55,10 +55,6 @@ int meter_init_random(meter_t *mtr, list_t options) {
|
|||
return SUCCESS;
|
||||
}
|
||||
|
||||
void meter_free_random(meter_t *mtr) {
|
||||
//meter_handle_random_t *handle = &mtr->handle.random;
|
||||
}
|
||||
|
||||
int meter_open_random(meter_t *mtr) {
|
||||
//meter_handle_random_t *handle = &mtr->handle.random;
|
||||
|
||||
|
|
|
@ -59,12 +59,6 @@ int meter_init_s0(meter_t *mtr, list_t options) {
|
|||
return SUCCESS;
|
||||
}
|
||||
|
||||
void meter_free_s0(meter_t *mtr) {
|
||||
meter_handle_s0_t *handle = &mtr->handle.s0;
|
||||
|
||||
free(handle->device);
|
||||
}
|
||||
|
||||
int meter_open_s0(meter_t *mtr) {
|
||||
meter_handle_s0_t *handle = &mtr->handle.s0;
|
||||
|
||||
|
|
|
@ -104,18 +104,6 @@ int meter_init_sml(meter_t *mtr, list_t options) {
|
|||
return SUCCESS;
|
||||
}
|
||||
|
||||
void meter_free_sml(meter_t *mtr) {
|
||||
meter_handle_sml_t *handle = &mtr->handle.sml;
|
||||
|
||||
if (handle->device != NULL) {
|
||||
free(handle->device);
|
||||
}
|
||||
|
||||
if (handle->host != NULL) {
|
||||
free(handle->host);
|
||||
}
|
||||
}
|
||||
|
||||
int meter_open_sml(meter_t *mtr) {
|
||||
meter_handle_sml_t *handle = &mtr->handle.sml;
|
||||
|
||||
|
|
|
@ -25,32 +25,10 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "reading.h"
|
||||
#include "meter.h"
|
||||
|
||||
char * reading_id_registry(const char *str) {
|
||||
static list_t strings;
|
||||
|
||||
char *found = NULL;
|
||||
|
||||
/* linear search in string list */
|
||||
foreach(strings, it, const char *) {
|
||||
if (strcmp(*it, str) == 0) {
|
||||
found = *it;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
found = strdup(str);
|
||||
list_push(&strings, found);
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
int reading_id_compare(meter_protocol_t protocol, reading_id_t a, reading_id_t b) {
|
||||
switch (protocol) {
|
||||
case meter_protocol_d0:
|
||||
|
@ -62,10 +40,7 @@ int reading_id_compare(meter_protocol_t protocol, reading_id_t a, reading_id_t b
|
|||
|
||||
case meter_protocol_file:
|
||||
case meter_protocol_exec:
|
||||
/* we only need to compare the base pointers here,
|
||||
because each identifer exists only once in the registry
|
||||
and has therefore a unique pointer */
|
||||
return !(a.string == b.string);
|
||||
return strcmp(a.string, b.string);
|
||||
|
||||
default:
|
||||
/* no channel id, adding all readings to buffer */
|
||||
|
@ -106,7 +81,7 @@ int reading_id_parse(meter_protocol_t protocol, reading_id_t *id, const char *st
|
|||
|
||||
case meter_protocol_file:
|
||||
case meter_protocol_exec:
|
||||
id->string = reading_id_registry(string);
|
||||
id->string = strdup(string); // TODO free() elsewhere
|
||||
break;
|
||||
|
||||
default: /* ignore other protocols which do not provide id's */
|
||||
|
|
|
@ -120,22 +120,9 @@ void * reading_thread(void *arg) {
|
|||
|
||||
/* debugging */
|
||||
if (options.verbosity >= log_debug) {
|
||||
size_t dump_len = 24;
|
||||
char *dump = malloc(dump_len);
|
||||
|
||||
if (dump == NULL) {
|
||||
print(log_error, "cannot allocate buffer", ch);
|
||||
}
|
||||
|
||||
while (dump == NULL || buffer_dump(buf, dump, dump_len) == NULL) {
|
||||
dump_len *= 1.5;
|
||||
free(dump);
|
||||
dump = malloc(dump_len);
|
||||
}
|
||||
|
||||
print(log_debug, "Buffer dump (size=%i keep=%i): %s", ch, buf->size, buf->keep, dump);
|
||||
|
||||
free(dump);
|
||||
char dump[1024];
|
||||
buffer_dump(buf, dump, 1024);
|
||||
print(log_debug, "Buffer dump: %s (size=%i, keep=%i)", ch, dump, buf->size, buf->keep);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,21 +138,14 @@ void * reading_thread(void *arg) {
|
|||
}
|
||||
|
||||
void logging_thread_cleanup(void *arg) {
|
||||
api_handle_t *api = (api_handle_t *) arg;
|
||||
|
||||
api_free(api);
|
||||
curl_easy_cleanup((CURL *) arg); /* always cleanup */
|
||||
}
|
||||
|
||||
void * logging_thread(void *arg) {
|
||||
channel_t *ch = (channel_t *) arg; /* casting argument */
|
||||
api_handle_t api;
|
||||
|
||||
if (api_init(ch, &api) != SUCCESS) {
|
||||
print(log_error, "CURL: cannot create handle", ch);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
pthread_cleanup_push(&logging_thread_cleanup, &api);
|
||||
CURL *curl = api_curl_init(ch);
|
||||
|
||||
pthread_cleanup_push(&logging_thread_cleanup, curl);
|
||||
|
||||
do { /* start thread mainloop */
|
||||
CURLresponse response;
|
||||
|
@ -191,30 +171,28 @@ void * logging_thread(void *arg) {
|
|||
|
||||
print(log_debug, "JSON request body: %s", ch, json_str);
|
||||
|
||||
curl_easy_setopt(api.curl, CURLOPT_POSTFIELDS, json_str);
|
||||
curl_easy_setopt(api.curl, CURLOPT_WRITEFUNCTION, curl_custom_write_callback);
|
||||
curl_easy_setopt(api.curl, CURLOPT_WRITEDATA, (void *) &response);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_str);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_custom_write_callback);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *) &response);
|
||||
|
||||
curl_code = curl_easy_perform(api.curl);
|
||||
curl_easy_getinfo(api.curl, CURLINFO_RESPONSE_CODE, &http_code);
|
||||
curl_code = curl_easy_perform(curl);
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
|
||||
|
||||
/* check response */
|
||||
if (curl_code != CURLE_OK) {
|
||||
print(log_error, "CURL: %s", ch, curl_easy_strerror(curl_code));
|
||||
}
|
||||
else if (http_code != 200) {
|
||||
char exception[255];
|
||||
if (api_parse_exception(response, exception, 255) == SUCCESS) {
|
||||
print(log_error, "Request failed: [%i] %s", ch, http_code, exception);
|
||||
}
|
||||
else {
|
||||
print(log_error, "Request failed: %i", ch, http_code);
|
||||
}
|
||||
}
|
||||
else {
|
||||
print(log_debug, "Request succeeded: %i", ch, http_code);
|
||||
if (curl_code == CURLE_OK && http_code == 200) { /* everything is ok */
|
||||
print(log_debug, "Request succeeded with code: %i", ch, http_code);
|
||||
ch->buffer.sent = last->next;
|
||||
}
|
||||
else { /* error */
|
||||
if (curl_code != CURLE_OK) {
|
||||
print(log_error, "CURL: %s", ch, curl_easy_strerror(curl_code));
|
||||
}
|
||||
else if (http_code != 200) {
|
||||
char err[255];
|
||||
api_parse_exception(response, err, 255);
|
||||
print(log_error, "Error from middleware: %s", ch, err);
|
||||
}
|
||||
}
|
||||
|
||||
/* householding */
|
||||
free(response.data);
|
||||
|
|
BIN
src/vzlogger
Executable file
BIN
src/vzlogger
Executable file
Binary file not shown.
|
@ -94,48 +94,48 @@ const char *long_options_descs[] = {
|
|||
* @param id could be NULL for general messages
|
||||
* @todo integrate into syslog
|
||||
*/
|
||||
void print(log_level_t level, const char *format, void *id, ... ) {
|
||||
void print(int level, const char *format, void *id, ... ) {
|
||||
va_list args;
|
||||
|
||||
if (level > options.verbosity) {
|
||||
return; /* skip message if its under the verbosity level */
|
||||
}
|
||||
|
||||
struct timeval now;
|
||||
struct tm * timeinfo;
|
||||
char prefix[24];
|
||||
size_t pos = 0;
|
||||
char buffer[1024];
|
||||
char *pos = buffer;
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
timeinfo = localtime(&now.tv_sec);
|
||||
|
||||
/* format timestamp */
|
||||
pos += strftime(prefix+pos, 18, "[%b %d %H:%M:%S]", timeinfo);
|
||||
/* print timestamp to buffer */
|
||||
pos += sprintf(pos, "[");
|
||||
pos += strftime(pos, 16, "%b %d %H:%M:%S", timeinfo);
|
||||
|
||||
/* format section */
|
||||
if (id) {
|
||||
snprintf(prefix+pos, 8, "[%s]", (char *) id);
|
||||
/* print logging 'section' */
|
||||
pos += (id != NULL) ? sprintf(pos, "][%s]", (char *) id) : sprintf(pos, "]");
|
||||
|
||||
/* fill with whitespaces */
|
||||
while(pos - buffer < 24) {
|
||||
pos += sprintf(pos, " ");
|
||||
}
|
||||
|
||||
va_list args;
|
||||
/* print formatstring */
|
||||
va_start(args, id);
|
||||
/* print to stdout/stderr */
|
||||
if (getppid() != 1) { /* running as fork in background? */
|
||||
FILE *stream = (level > 0) ? stdout : stderr;
|
||||
|
||||
fprintf(stream, "%-24s", prefix);
|
||||
vfprintf(stream, format, args);
|
||||
fprintf(stream, "\n");
|
||||
}
|
||||
pos += vsprintf(pos, format, args);
|
||||
va_end(args);
|
||||
|
||||
va_start(args, id);
|
||||
/* print to stdout/stderr */
|
||||
if (getppid() != 1) {
|
||||
fprintf((level > 0) ? stdout : stderr, "%s\n", buffer);
|
||||
}
|
||||
|
||||
/* append to logfile */
|
||||
if (options.logfd) {
|
||||
fprintf(options.logfd, "%-24s", prefix);
|
||||
vfprintf(options.logfd, format, args);
|
||||
fprintf(options.logfd, "\n");
|
||||
fflush(options.logfd);
|
||||
fprintf(options.logfd, "%s\n", buffer);
|
||||
fflush(options.logfd);
|
||||
}
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -273,7 +273,6 @@ int config_parse_cli(int argc, char * argv[], config_options_t * options) {
|
|||
break;
|
||||
|
||||
case 'c': /* config file */
|
||||
free(options->config);
|
||||
options->config = strdup(optarg);
|
||||
break;
|
||||
|
||||
|
@ -307,8 +306,8 @@ int config_parse_cli(int argc, char * argv[], config_options_t * options) {
|
|||
*/
|
||||
int main(int argc, char *argv[]) {
|
||||
/* default options */
|
||||
options.config = strdup("/etc/vzlogger.conf");
|
||||
options.log = NULL;
|
||||
options.config = "/etc/vzlogger.conf";
|
||||
options.log = "/var/log/vzlogger.log";
|
||||
options.logfd = NULL;
|
||||
options.port = 8080;
|
||||
options.verbosity = 0;
|
||||
|
@ -389,7 +388,7 @@ int main(int argc, char *argv[]) {
|
|||
ch->buffer.keep = ceil(options.buffer_length / (double) mapping->meter.interval);
|
||||
}
|
||||
|
||||
if (options.logging) {
|
||||
if (ch->status != status_running && options.logging) {
|
||||
pthread_create(&ch->thread, NULL, &logging_thread, (void *) ch);
|
||||
print(log_debug, "Logging thread started", ch);
|
||||
}
|
||||
|
@ -423,10 +422,9 @@ int main(int argc, char *argv[]) {
|
|||
channel_free(ch);
|
||||
}
|
||||
|
||||
meter_close(mtr); /* closing connection */
|
||||
|
||||
list_free(&mapping->channels);
|
||||
meter_free(mtr);
|
||||
|
||||
meter_close(mtr); /* closing connection */
|
||||
}
|
||||
|
||||
#ifdef LOCAL_SUPPORT
|
||||
|
@ -437,13 +435,11 @@ int main(int argc, char *argv[]) {
|
|||
#endif /* LOCAL_SUPPORT */
|
||||
|
||||
/* householding */
|
||||
free(options.config);
|
||||
list_free(&mappings);
|
||||
curl_global_cleanup();
|
||||
|
||||
/* close logfile */
|
||||
if (options.logfd) {
|
||||
free(options.log);
|
||||
fclose(options.logfd);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue