From 0911a39b28f734a789cb87506b1307312ae31f66 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Tue, 27 Dec 2011 14:45:19 +0100 Subject: [PATCH] Daemon mode --- Makefile | 4 +- TODO | 4 +- arexx.c => arexxd.c | 244 +++++++++++++++++++++++++++++++++++--------- 3 files changed, 197 insertions(+), 55 deletions(-) rename arexx.c => arexxd.c (62%) diff --git a/Makefile b/Makefile index 04cfded..6d5a256 100644 --- a/Makefile +++ b/Makefile @@ -3,8 +3,8 @@ LD=gcc CFLAGS=-O2 -Wall -W -Wno-parentheses -Wstrict-prototypes -Wmissing-prototypes -Wundef -Wredundant-decls -std=gnu99 LDLIBS=-lusb-1.0 -lm -lrrd -all: arexx +all: arexxd clean: rm -f `find . -name "*~" -or -name "*.[oa]" -or -name "\#*\#" -or -name TAGS -or -name core -or -name .depend -or -name .#*` - rm -f arexx + rm -f arexxd diff --git a/TODO b/TODO index 1eef6b0..c5b8d9f 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,2 @@ -- Print of messages -- use syslog? -- Handle disconnect and reconnect of the receiver -- Periodical synchronization of time - Multiple receivers? +- Logging of min/max temperatures diff --git a/arexx.c b/arexxd.c similarity index 62% rename from arexx.c rename to arexxd.c index 796d13a..6e301a0 100644 --- a/arexx.c +++ b/arexxd.c @@ -9,34 +9,80 @@ #include #include #include +#include #include #include +#include +#include +#include +#include #include #include #include +#define LOG_PATH "/var/log/arexxd" + typedef unsigned char byte; static libusb_context *usb_ctxt; static libusb_device_handle *devh; -static int debug_packets = 0; -static int debug_raw_data = 0; - -#define TIME_OFFSET 946681200 // Timestamp of 2000-01-01 00:00:00 +static int use_syslog; +static int debug_mode; +static int debug_packets; +static int debug_raw_data; -static void die(char *msg, ...) +static void die(char *fmt, ...) { va_list args; - va_start(args, msg); - vfprintf(stderr, msg, args); - fputc('\n', stderr); + va_start(args, fmt); + if (use_syslog) + vsyslog(LOG_CRIT, fmt, args); + else { + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); + } va_end(args); exit(1); } +static void log_error(char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + if (use_syslog) + vsyslog(LOG_ERR, fmt, args); + else { + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); + } + va_end(args); +} + +static void log_info(char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + if (use_syslog) + vsyslog(LOG_INFO, fmt, args); + else { + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); + } + va_end(args); +} + +static void log_pkt(char *fmt, ...) +{ + if (!debug_packets) + return; + va_list args; + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); +} + /*** RRD interface ***/ -#define RRD_NAME "/tmp/power.rrd" #define SLOT_SIZE 10 // 10 seconds per averaging slot #define MAX_ARGS 20 #define MAX_ARG_SIZE 1024 @@ -75,7 +121,7 @@ static void rrd_point(time_t t, int id, double val) struct stat st; if (stat(rr_name, &st) < 0 || !st.st_size) { // We have to create the RRD - printf("### Creating %s\n", rr_name); + log_info("Creating %s", rr_name); arg_new(); arg_push(rr_name); arg_push("--start"); @@ -86,8 +132,10 @@ static void rrd_point(time_t t, int id, double val) 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()); + if (rrd_test_error()) { + log_error("rrd_create on %s failed: %s", rr_name, rrd_get_error()); + return; + } } arg_new(); @@ -95,11 +143,13 @@ static void rrd_point(time_t t, int id, double val) 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()); + log_error("rrd_update on %s failed: %s", rr_name, rrd_get_error()); } /*** Transforms ***/ +#define TIME_OFFSET 946681200 // Timestamp of 2000-01-01 00:00:00 + static void cooked_point(time_t t, int id, double val, char *unit, int q) { struct tm tm; @@ -108,7 +158,8 @@ static void cooked_point(time_t t, int id, double val, char *unit, int q) char tbuf[64]; 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); + if (debug_raw_data) + printf("== %s id=%d val=%.3f unit=%s q=%d\n", tbuf, id, val, unit, q); rrd_point(t, id, val); } @@ -193,12 +244,12 @@ static void raw_point(int t, int id, int raw, int q) unit = "ppm"; } } else { - printf("### Unknown sensor type 0x%04x\n", id); + log_error("Unknown sensor type 0x%04x", id); return; } if (z < lo || z > hi) { - printf("### Sensor %d: value %f out of range\n", id, z); + log_error("Sensor %d: value %f out of range", id, z); return; } @@ -207,41 +258,56 @@ static void raw_point(int t, int id, int raw, int q) /*** USB interface ***/ -static void find_device(void) +static int 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); + if (devn < 0) { + log_error("Cannot enumerate USB devices: error %d", (int) devn); + return 0; + } for (ssize_t i=0; i> xmit timed out\n"); + return 0; + } + log_error("Transmit error: %d", err); + return err; } if (debug_packets) { - printf(">> xmit %d bytes\n", transferred); + log_pkt(">> 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 (err == LIBUSB_ERROR_TIMEOUT) { + log_pkt(">> recv timed out\n"); + return 0; + } + log_error("Receive error: %d", err); + return err; } if (debug_packets) - printf("<< recv %d bytes\n", transferred); + log_pkt("<< recv %d bytes\n", transferred); while (transferred < 64) reply[transferred++] = 0xff; if (debug_packets) @@ -299,7 +373,7 @@ static void put_le32(byte *p, unsigned int x) static int parse_packet(byte *reply) { if (reply[0]) { - printf("### Unknown packet type %02x\n", reply[0]); + log_error("Unknown packet type %02x", reply[0]); return 0; } @@ -311,11 +385,11 @@ static int parse_packet(byte *reply) if (!len || len == 0xff) break; if (len < 9 || len > 10) { - printf("### Unknown tuple length %02x\n", len); + log_error("Unknown tuple length %02x", len); break; } if (pos + len > 64) { - printf("### Tuple truncated\n"); + log_error("Tuple truncated"); break; } int id = get_le16(p+1); @@ -338,7 +412,7 @@ static int parse_packet(byte *reply) static void set_clock(void) { - puts("### Syncing time"); + log_info("Synchronizing receiver time"); byte req[64], reply[64]; memset(req, 0, 64); @@ -359,25 +433,95 @@ static void set_clock(void) #endif } -int main(void) +/*** Main ***/ + +static const struct option long_options[] = { + { "debug", 0, NULL, 'd' }, + { "log-packets", 0, NULL, 'p' }, + { NULL, 0, NULL, 0 }, +}; + +static void usage(void) +{ + fprintf(stderr, "Usage: arexxd [--debug] [--log-packets]\n"); + exit(1); +} + +int main(int argc, char **argv) { + int opt; + while ((opt = getopt_long(argc, argv, "dp", long_options, NULL)) >= 0) + switch (opt) { + case 'd': + debug_mode++; + break; + case 'p': + debug_packets++; + debug_raw_data++; + break; + default: + usage(); + } + if (optind < argc) + usage(); + int err; if (err = libusb_init(&usb_ctxt)) die("Cannot initialize libusb: error %d", err); - libusb_set_debug(usb_ctxt, 3); - - find_device(); - set_clock(); + // libusb_set_debug(usb_ctxt, 3); + + if (!debug_mode) { + if (chdir(LOG_PATH) < 0) + die("Cannot change directory to %s: %m", LOG_PATH); + if (debug_packets || debug_raw_data) { + close(1); + if (open("debug", O_WRONLY | O_CREAT | O_APPEND, 0666) < 0) + die("Cannot open debug log: %m"); + setlinebuf(stdout); + } + openlog("arexxd", LOG_NDELAY, LOG_DAEMON); + pid_t pid = fork(); + if (pid < 0) + die("fork() failed: %m"); + if (pid) + return 0; + setsid(); + use_syslog = 1; + } + int inited = 0; for (;;) { - byte req[64], reply[64]; - memset(req, 0, sizeof(req)); - req[0] = 3; - if (send_and_receive(req, reply)) { - if (parse_packet(reply)) + if (!find_device()) { + if (!inited) { + inited = 1; + log_error("Receiver not connected, waiting until it appears"); + } + sleep(30); + continue; + } + + inited = 1; + + int sync_in = 0; + for (;;) { + if (!sync_in) { + set_clock(); + sync_in = 100; + } + byte req[64], reply[64]; + memset(req, 0, sizeof(req)); + req[0] = 3; + err = send_and_receive(req, reply); + if (err < 0) + break; + if (err > 0 && parse_packet(reply)) continue; + sleep(4); + sync_in--; } - sleep(4); + + log_info("Disconnecting receiver"); + release_device(); } return 0; -- 2.39.2