#include #include #include #include #include #include #include #include #include #include #include "serial-util.h" #include #include int hex = 0; int dec = 0; int screen = 0; int unprocessed = 0; int process(const uint8_t *buf, int len); int main(int argc, char *argv[]) { char *device=strdup("/dev/serial/by-id/usb-FTDI_FT232R_" "USB_UART_A6007wc5-if00-port0"); int rate=500000; int fd; int getopt_index; char buf[1024]; int len; int calibrate = 1; static struct option long_opts[] = { { "device", required_argument, NULL, 'd' }, { "rate", required_argument, NULL, 'r' }, { "hex", no_argument, NULL, 'x' }, { "dec", no_argument, NULL, 'D' }, { "unprocessed", no_argument, NULL, 'u' }, { "no-calibrate", no_argument, NULL, 'n' }, { "screen", no_argument, NULL, 's' }, { "help", no_argument, NULL, 'h' }, { 0, 0, 0, 0 } }; int help=0; char c; while ((c = getopt_long(argc, argv, "d:r:xDunsh?", long_opts, &getopt_index)) != -1) { switch(c) { case 'd': free(device); device = strdup(optarg); break; case 'r': rate = atoi(optarg); if(rate == 0) errx(1, "invalid rate: %s",optarg); break; case 'x': hex = 1; break; case 'D': dec = 1; break; case 'u': unprocessed = 1; break; case 'n': calibrate = 0; break; case 's': screen = 1; break; case 'h': case '?': default: help = 1; break; } } if (help) { fprintf(stderr, "Zoom Nilm Client\n"); fprintf(stderr, "usage: %s [options]\n\n", *argv); fprintf(stderr, " -d, --device %-14s serial port\n", device); fprintf(stderr, " -r, --rate %-16d baud rate\n", rate); fprintf(stderr, " -x, --hex hex out\n"); fprintf(stderr, " -D, --dec dec out\n"); fprintf(stderr, " -u, --unprocessed " "dump raw unprocessed data\n"); fprintf(stderr, " -n, --no-calibrate " "skip calibration routine\n"); fprintf(stderr, " -s, --screen " "send \\r instead of \\n\n"); fprintf(stderr, " -h, --help this cruft\n"); return 1; } if ((fd = serial_open(device, rate)) == -1) err(1, "serial_open failed for %s", device); if (calibrate) { fprintf(stderr, "performing calibration\n"); char c = 'c'; write(fd, &c, 1); drain(fd); } len = 0; while (1) { int processed, n; n = read(fd, buf + len, sizeof(buf) - len); if (n <= 0) err(1, "read"); len += n; processed = process((uint8_t *) buf, len); memmove(buf, buf + processed, len - processed); len -= processed; } return 1; } int process_adc_dac(const uint8_t *buf) { uint16_t dac, tmp; int16_t adc; int overflow; /* data OK? */ if ((buf[0] & 0xC0) != 0) return 0; /* extract */ if (buf[0] & 0x10) overflow = 1; else overflow = 0; tmp = ((buf[0] & 0x0F) << 8) | buf[1]; /* sign-extend ADC value */ if (tmp & 0x0800) tmp |= 0xF000; else tmp &= ~0xF000; adc = (int16_t)tmp; dac = (buf[2] << 8) | buf[3]; /* send it out */ if (hex) { printf("%04x %03x", dac, adc & 0x0FFF); } else if (dec) { printf("%d %d", dac, adc); } else { printf("DAC: %5d ADC: % 5d Total: xxx", dac, adc); if (overflow) printf(" **** adc may have clamped"); } if (screen) printf("\033[K\r"); else printf("\n"); return 1; } int process_calibration(const uint8_t *buf) { float f = *(float *)buf; fprintf(stderr, "got calibration value: %f\n", f); return 1; } int process(const uint8_t *buf, int len) { int n = 0; if (unprocessed) { n = write(fileno(stdout), buf, len); if (n >= 0) return n; return 0; } /* Process blocks */ retry: for (; (n + 5) <= len; buf += 5, n += 5) { int ok = 0; switch (buf[0]) { case 0xA0: if (process_adc_dac(buf + 1)) ok = 1; break; case 0xA1: if (process_calibration(buf + 1)) ok = 1; break; default: break; } if (!ok) { /* badly formed data; eat one byte and retry */ fprintf(stderr,"throwing away 0x%02x '%c'\n", buf[0], isprint(buf[0]) ? buf[0] : '.'); buf++; n++; goto retry; } } return n; }