From 889ac656591c0cc0c0a3ce114f33144561a9618d Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Mon, 26 Dec 2011 22:09:15 +0100 Subject: [PATCH] Record data in a RRD --- Makefile | 2 +- arexx.c | 222 ++++++++++++++++++++++++++++++++++++------------------- 2 files changed, 148 insertions(+), 76 deletions(-) diff --git a/Makefile b/Makefile index e136433..04cfded 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ CC=gcc LD=gcc CFLAGS=-O2 -Wall -W -Wno-parentheses -Wstrict-prototypes -Wmissing-prototypes -Wundef -Wredundant-decls -std=gnu99 -LDLIBS=-lusb-1.0 -lm +LDLIBS=-lusb-1.0 -lm -lrrd all: arexx diff --git a/arexx.c b/arexx.c index 95c9c93..796d13a 100644 --- a/arexx.c +++ b/arexx.c @@ -11,7 +11,9 @@ #include #include #include +#include #include +#include typedef unsigned char byte; static libusb_context *usb_ctxt; @@ -32,94 +34,71 @@ static void die(char *msg, ...) exit(1); } -static void find_device(void) -{ - libusb_device **devlist; - ssize_t devn = libusb_get_device_list(usb_ctxt, &devlist); - if (devn < 0) - die("Cannot enumerate USB devices: error %d\n", (int) devn); - - for (ssize_t i=0; i> xmit %d bytes\n", transferred); - dump_packet(req); - } - if (err = libusb_bulk_transfer(devh, 0x81, reply, 64, &transferred, 200)) { - fprintf(stderr, "Receive error: %d\n", err); - return 0; - } - if (debug_packets) - printf("<< recv %d bytes\n", transferred); - while (transferred < 64) - reply[transferred++] = 0xff; - if (debug_packets) - dump_packet(reply); - return 1; -} +static int arg_cnt; +static char *arg_ptr[MAX_ARGS+1]; +static char arg_buf[MAX_ARG_SIZE]; +static int arg_pos; -static unsigned int get_be16(byte *p) +static void arg_new(void) { - return p[1] | (p[0] << 8); + arg_cnt = 1; + arg_pos = 0; + arg_ptr[0] = "rrdtool"; } -static unsigned int get_le16(byte *p) +static void arg_push(const char *fmt, ...) { - return p[0] | (p[1] << 8); + if (arg_cnt >= MAX_ARGS) + die("MAX_ARGS exceeded"); + va_list va; + va_start(va, fmt); + int len = 1 + vsnprintf(arg_buf + arg_pos, MAX_ARG_SIZE - arg_pos, fmt, va); + if (arg_pos + len > MAX_ARG_SIZE) + die("MAX_ARG_SIZE exceeded"); + arg_ptr[arg_cnt++] = arg_buf + arg_pos; + arg_ptr[arg_cnt] = NULL; + arg_pos += len; } -static unsigned int get_le32(byte *p) +static void rrd_point(time_t t, int id, double val) { - return get_le16(p) | (get_le16(p+2) << 16); -} + char rr_name[256]; + snprintf(rr_name, sizeof(rr_name), "sensor-%d.rrd", id); + + struct stat st; + if (stat(rr_name, &st) < 0 || !st.st_size) { + // We have to create the RRD + printf("### Creating %s\n", rr_name); + arg_new(); + arg_push(rr_name); + arg_push("--start"); + arg_push("%d", (int) time(NULL) - 28*86400); + arg_push("--step"); + arg_push("60"); + arg_push("DS:temp:GAUGE:300:0:10000"); // Anything over 10 kW is considered a ghost + arg_push("RRA:AVERAGE:0.25:1:20160"); // Last 14 days with full resolution + arg_push("RRA:AVERAGE:0.25:60:88800"); // Last 10 years with 1h resolution + rrd_create(arg_cnt, arg_ptr); + if (rrd_test_error()) + die("rrd_create failed: %s", rrd_get_error()); + } -static void put_le16(byte *p, unsigned int x) -{ - p[0] = x; - p[1] = x >> 8; + arg_new(); + arg_push(rr_name); + arg_push("%d:%f", t, val); + rrd_update(arg_cnt, arg_ptr); + if (rrd_test_error()) + printf("### rrd_update failed: %s\n", rrd_get_error()); } -static void put_le32(byte *p, unsigned int x) -{ - put_le16(p, x); - put_le16(p+2, x>>16); -} +/*** Transforms ***/ static void cooked_point(time_t t, int id, double val, char *unit, int q) { @@ -130,6 +109,8 @@ static void cooked_point(time_t t, int id, double val, char *unit, int q) strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %H:%M:%S", &tm); printf("== %s id=%d val=%.3f unit=%s q=%d\n", tbuf, id, val, unit, q); + + rrd_point(t, id, val); } static void raw_point(int t, int id, int raw, int q) @@ -224,6 +205,97 @@ static void raw_point(int t, int id, int raw, int q) cooked_point(t + TIME_OFFSET, id, z, unit, q); } +/*** USB interface ***/ + +static void find_device(void) +{ + libusb_device **devlist; + ssize_t devn = libusb_get_device_list(usb_ctxt, &devlist); + if (devn < 0) + die("Cannot enumerate USB devices: error %d\n", (int) devn); + + for (ssize_t i=0; i> xmit %d bytes\n", transferred); + dump_packet(req); + } + if (err = libusb_bulk_transfer(devh, 0x81, reply, 64, &transferred, 200)) { + fprintf(stderr, "Receive error: %d\n", err); + return 0; + } + if (debug_packets) + printf("<< recv %d bytes\n", transferred); + while (transferred < 64) + reply[transferred++] = 0xff; + if (debug_packets) + dump_packet(reply); + return 1; +} + +static unsigned int get_be16(byte *p) +{ + return p[1] | (p[0] << 8); +} + +static unsigned int get_le16(byte *p) +{ + return p[0] | (p[1] << 8); +} + +static unsigned int get_le32(byte *p) +{ + return get_le16(p) | (get_le16(p+2) << 16); +} + +static void put_le16(byte *p, unsigned int x) +{ + p[0] = x; + p[1] = x >> 8; +} + +static void put_le32(byte *p, unsigned int x) +{ + put_le16(p, x); + put_le16(p+2, x>>16); +} + static int parse_packet(byte *reply) { if (reply[0]) { -- 2.39.2