2 * wattsup - Program for controlling the Watts Up? Pro Device
5 * Copyright (c) 2005 Patrick Mochel
7 * This program is released under the GPLv2
12 * gcc -O2 -Wall -o wattsup wattsup.c
32 static const char * wu_version = "0.02";
35 #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
37 static const char * prog_name = "wattsup";
39 static const char * sysfs_path_start = "/sys/class/tty";
41 static char * wu_device = "ttyUSB0";
43 static int wu_count = 0;
44 static int wu_debug = 0;
45 static char *wu_delim = ", ";
46 static int wu_final = 0;
47 static int wu_interval = 1;
48 static int wu_label = 0;
49 static int wu_newline = 0;
50 static int wu_suppress = 0;
52 static int wu_localtime = 0;
53 static int wu_gmtime = 0;
55 static int wu_info_all = 0;
56 static int wu_no_data = 0;
57 static int wu_set_only = 0;
60 #define wu_num_fields 18
61 #define wu_param_len 16
69 char * field[wu_num_fields];
70 char * label[wu_num_fields];
78 unsigned int watt_hours;
83 unsigned int max_watts;
85 unsigned int max_volts;
86 unsigned int max_amps;
87 unsigned int min_watts;
88 unsigned int min_volts;
90 unsigned int min_amps;
91 unsigned int power_factor;
92 unsigned int duty_cycle;
93 unsigned int power_cycle;
107 int (*show)(int dev_fd);
108 int (*store)(int dev_fd);
141 static char * wu_option_value(unsigned int index);
162 wu_field_power_factor,
164 wu_field_power_cycle,
173 static struct wu_field wu_fields[wu_num_fields] = {
176 .descr = "Watt Consumption",
179 [wu_field_min_watts] = {
181 .descr = "Minimum Watts Consumed",
184 [wu_field_max_watts] = {
186 .descr = "Maxium Watts Consumed",
191 .descr = "Volts Consumption",
194 [wu_field_min_volts] = {
196 .descr = "Minimum Volts Consumed",
199 [wu_field_max_volts] = {
201 .descr = "Maximum Volts Consumed",
206 .descr = "Amp Consumption",
209 [wu_field_min_amps] = {
211 .descr = "Minimum Amps Consumed",
214 [wu_field_max_amps] = {
216 .descr = "Maximum Amps Consumed",
219 [wu_field_watt_hours] = {
221 .descr = "Average KWH",
224 [wu_field_mo_kwh] = {
226 .descr = "Average monthly KWH",
231 .descr = "Cost per watt",
234 [wu_field_mo_cost] = {
236 .descr = "Monthly Cost",
239 [wu_field_power_factor] = {
240 .name = "power-factor",
241 .descr = "Ratio of Watts vs. Volt Amps",
244 [wu_field_duty_cycle] = {
245 .name = "duty-cycle",
246 .descr = "Percent of the Time On vs. Time Off",
249 [wu_field_power_cycle] = {
250 .name = "power-cycle",
251 .descr = "Indication of power cycle",
258 static void msg_start(const char * fmt, ...)
266 static void msg_end(void)
271 static void msg(const char * fmt, ...)
280 static void dbg(const char * fmt, ...)
286 msg_start("%s: [debug] ", prog_name);
293 static void err(const char * fmt, ...)
298 fprintf(stderr, "%s: [error] ", prog_name);
299 vfprintf(stderr, fmt, ap);
300 fprintf(stderr, "\n");
304 static void perr(const char * fmt, ...)
311 n = sprintf(buf, "%s: [error] ", prog_name);
312 vsnprintf(buf + n, sizeof(buf) - n, fmt, ap);
317 static int ret_err(int err)
324 static void print_packet(struct wu_packet * p, char * str)
329 msg_start("Watts Up? %s\n", str);
330 for (i = 0; i< p->count; i++) {
332 msg("%s", wu_newline ? "\n" : wu_delim);
334 msg("[%s] ", p->label[i]);
341 static void print_time(void)
346 if (wu_localtime || wu_gmtime) {
354 msg("[%02d:%02d:%02d] ",
355 tm->tm_hour, tm->tm_min, tm->tm_sec);
359 static void print_packet_filter(struct wu_packet * p,
360 int (*filter_ok)(struct wu_packet * p, int i, char * str))
367 for (i = 0, printed = 0; i< p->count; i++) {
368 if (!filter_ok(p, i, buf))
372 msg("%s", wu_newline ? "\n" : wu_delim);
374 msg("[%s] ", p->label[i]);
382 * Device should be something like "ttyS0"
385 static int open_device(char * device_name, int * dev_fd)
391 cur_fd = open(".", O_RDONLY);
393 perr("Could not open current directory.");
397 ret = chdir(sysfs_path_start);
399 perr(sysfs_path_start);
404 * First, check if /sys/class/tty/<name>/ exists.
407 dbg("Checking sysfs path: %s/%s", sysfs_path_start, device_name);
409 ret = stat(device_name,&s);
415 if (!S_ISDIR(s.st_mode)) {
417 err("%s is not a TTY device.", device_name);
421 dbg("%s is a registered TTY device", device_name);
427 * Check if device node exists and is writable
431 ret = stat(device_name,&s);
433 perr("/dev/%s (device node)", device_name);
437 if (!S_ISCHR(s.st_mode)) {
440 err("%s is not a TTY character device.", device_name);
444 dbg("%s has a device node", device_name);
446 ret = access(device_name, R_OK | W_OK);
448 perr("%s: Not writable?", device_name);
452 ret = open(device_name, O_RDWR | O_NONBLOCK);
454 perr("Could not open %s");
466 static int setup_serial_device(int dev_fd)
471 ret = tcgetattr(dev_fd,&t);
476 cfsetispeed(&t, B115200);
477 cfsetospeed(&t, B115200);
478 tcflush(dev_fd, TCIFLUSH);
482 ret = tcsetattr(dev_fd, TCSANOW,&t);
485 perr("setting terminal attributes");
493 static int wu_write(int fd, struct wu_packet * p)
500 memset(p->buf, 0, sizeof(p->buf));
501 n = sprintf(p->buf, "#%c,%c,%d", p->cmd, p->sub_cmd, p->count);
505 for (i = 0; i< p->count; i++) {
506 if ((p->len + strlen(p->field[i]) + 4)>= sizeof(p->buf)) {
507 err("Overflowed command string");
508 return ret_err(EOVERFLOW);
510 n = sprintf(s, ",%s", p->field[i]);
514 p->buf[p->len++] = ';';
516 dbg("Writing '%s' (strlen = %d) (len = %d) to device",
517 p->buf, strlen(p->buf), p->len);
518 ret = write(fd, p->buf, p->len);
520 perr("Writing to device");
522 return ret>= 0 ? 0 : ret;
526 static void dump_packet(struct wu_packet * p)
530 dbg("Packet - Command '%c' %d parameters", p->cmd, p->count);
532 for (i = 0; i< p->count; i++)
533 dbg("[%2d] [%20s] = \"%s\"", i, p->label[i], p->field[i]);
537 static int parse_packet(struct wu_packet * p)
542 p->buf[p->len] = '\0';
544 dbg("Parsing Packet, Raw buffer is (%d bytes) [%s]",
550 * First character should be '#'
557 dbg("Invalid packet");
558 return ret_err(EFAULT);
561 dbg("Invalid packet");
562 return ret_err(EFAULT);
566 * Command character is first
568 next = strchr(s, ',');
573 dbg("Invalid Command field [%s]", s);
574 return ret_err(EFAULT);
578 * Next character is the subcommand, and should be '-'
579 * Though, it doesn't matter, because we just
582 next = strchr(s, ',');
587 dbg("Invalid 2nd field");
588 return ret_err(EFAULT);
592 * Next is the number of parameters,
593 * which should always be> 0.
595 next = strchr(s, ',');
601 dbg("Couldn't determine number of parameters");
602 return ret_err(EFAULT);
605 dbg("Have %d parameter%s (cmd = '%c')",
606 p->count, p->count> 1 ? "s" : "", p->cmd);
609 * Now, we loop over the rest of the string,
610 * storing a pointer to each in p->field[].
612 * The last character was originally a ';', but may have been
613 * overwritten with a '\0', so we make sure to catch
614 * that when converting the last parameter.
616 for (i = 0; i< p->count; i++) {
617 next = strpbrk(s, ",;");
621 if (i< (p->count - 1)) {
622 dbg("Malformed parameter string [%s]", s);
623 return ret_err(EFAULT);
628 * Skip leading white space in fields
640 static int wu_read(int fd, struct wu_packet * p)
652 ret = select(fd + 1,&read_fd, NULL, NULL,&tv);
654 perr("select on terminal device");
658 ret = read(fd, p->buf, wu_strlen);
660 perr("Reading from device");
665 dbg("Device timed out while reading");
666 return ret_err(ETIME);
668 return parse_packet(p);
672 static int wu_show_header(int fd)
674 struct wu_packet p = {
679 [0] = "watts header",
680 [1] = "volts header",
684 [5] = "mo. kWh header",
685 [6] = "mo. cost header",
686 [7] = "max watts header",
687 [8] = "max volts header",
688 [9] = "max amps header",
689 [10] = "min watts header",
690 [11] = "min volts header",
691 [12] = "min amps header",
692 [13] = "power factor header",
693 [14] = "duty cycle header",
694 [15] = "power cycle header",
699 ret = wu_write(fd,&p);
701 perr("Requesting header strings");
706 ret = wu_read(fd,&p);
708 perr("Reading header strings");
712 print_packet(&p, "Header Record");
718 static int wu_show_cal(int fd)
720 struct wu_packet p = {
726 [1] = "sample count",
732 [7] = "low amps gain",
733 [8] = "low amps bias",
734 [9] = "low amps offset",
736 [11] = "watts offset",
737 [12] = "low watts gain",
738 [13] = "low watts offset",
743 ret = wu_write(fd,&p);
745 perr("Requesting calibration parameters");
750 ret = wu_read(fd,&p);
752 perr("Reading header strings");
755 print_packet(&p, "Calibration Settings");
760 static int wu_start_log(void)
762 struct wu_packet p = {
777 ret = wu_write(wu_fd,&p);
781 perr("Starting External Logging");
787 static int wu_stop_log(void)
789 struct wu_packet p = {
801 * Stop logging and read time stamp.
803 ret = wu_write(wu_fd,&p);
805 perr("Stopping External Logging");
810 ret = wu_read(wu_fd,&p);
812 perr("Reading final time stamp");
816 print_packet(&p, "Final Time Stamp and Interval");
820 static int filter_data(struct wu_packet * p, int i, char * buf)
822 if (i< wu_num_fields) {
823 if (wu_fields[i].enable) {
824 double val = strtod(p->field[i], NULL);
825 snprintf(buf, 256, "%.1f", val / 10.0);
832 static int wu_clear(int fd)
834 struct wu_packet p = {
844 ret = wu_write(fd,&p);
846 perr("Clearing memory");
858 static int wu_read_data(int fd)
860 struct wu_packet p = {
875 [13] = "power factor",
877 [15] = "power cycle",
885 static const int wu_max_retry = 2;
890 ret = wu_read(fd,&p);
892 if (++retry< wu_max_retry) {
893 dbg("Bad record back, retrying\n");
896 } else if (retry == wu_max_retry) {
897 dbg("Still couldn't get a good record, resetting\n");
905 perr("Blech. Giving up on read");
910 dbg("[%d] ", num_read);
912 print_packet_filter(&p, filter_data);
914 if (wu_count&& (++i == wu_count))
924 static int wu_show_interval(int fd)
926 struct wu_packet p = {
937 ret = wu_write(fd,&p);
939 perr("Requesting interval");
944 ret = wu_read(fd,&p);
946 perr("Reading interval");
949 print_packet(&p, "Interval Settings");
954 static int wu_write_interval(int fd, unsigned int seconds,
955 unsigned int interval)
957 char str_seconds[wu_param_len];
958 char str_interval[wu_param_len];
959 struct wu_packet p = {
970 snprintf(str_seconds, wu_param_len, "%ud", seconds);
971 snprintf(str_interval, wu_param_len, "%ud", interval);
973 ret = wu_write(fd,&p);
975 perr("Setting Sampling Interval");
982 static int wu_store_interval(int fd)
984 char * s = wu_option_value(wu_option_interval);
987 wu_interval = strtol(s,&end, 0);
989 err("Invalid interval: %s", s);
990 return ret_err(EINVAL);
992 return wu_write_interval(fd, 1, wu_interval);
995 static int wu_show_mode(int fd)
997 struct wu_packet p = {
1002 [0] = "display mode",
1007 ret = wu_write(fd,&p);
1009 perr("Requesting device display mode");
1013 ret = wu_read(fd,&p);
1015 perr("Reaing device display mode");
1022 static int wu_write_mode(int fd, int mode)
1024 char str_mode[wu_param_len];
1025 struct wu_packet p = {
1035 snprintf(str_mode, wu_param_len, "%ud", mode);
1036 ret = wu_write(fd,&p);
1038 perr("Setting device display mode");
1044 static int wu_store_mode(int fd)
1046 char * s = wu_option_value(wu_option_mode);
1050 mode = strtol(s,&end, 0);
1052 err("Invalid mode: %s", s);
1053 return ret_err(EINVAL);
1055 return wu_write_mode(fd, mode);
1060 static int wu_show_user(int fd)
1062 struct wu_packet p = {
1067 [0] = "cost per kWh",
1068 [1] = "2nd tier cost",
1069 [2] = "2nd tier threshold",
1070 [3] = "duty cycle threshold",
1075 ret = wu_write(fd,&p);
1077 perr("Requesting user parameters");
1082 ret = wu_read(fd,&p);
1084 perr("Reading user parameters");
1087 print_packet(&p, "User Settings");
1092 static int wu_write_user(int fd, unsigned int kwh_cost,
1093 unsigned int second_tier_cost,
1094 unsigned int second_tier_threshold,
1095 unsigned int duty_cycle_threshold)
1097 char str_kwh_cost[wu_param_len];
1098 char str_2nd_tier_cost[wu_param_len];
1099 char str_2nd_tier_threshold[wu_param_len];
1100 char str_duty_cycle_threshold[wu_param_len];
1102 struct wu_packet p = {
1108 [1] = str_2nd_tier_cost,
1109 [2] = str_2nd_tier_threshold,
1110 [3] = str_duty_cycle_threshold,
1115 snprintf(str_kwh_cost, wu_param_len, "%ud", kwh_cost);
1116 snprintf(str_2nd_tier_cost, wu_param_len, "%ud",
1118 snprintf(str_2nd_tier_threshold, wu_param_len, "%ud",
1119 second_tier_threshold);
1120 snprintf(str_duty_cycle_threshold, wu_param_len, "%ud",
1121 duty_cycle_threshold);
1123 ret = wu_write(fd,&p);
1125 perr("Writing user parameters");
1131 static int wu_store_user(int fd)
1133 unsigned int kwh_cost;
1134 unsigned int second_tier_cost;
1135 unsigned int second_tier_threshold;
1136 unsigned int duty_cycle_threshold;
1137 char * buf = wu_option_value(wu_option_user);
1142 err("No user parameters?");
1143 return ret_err(EINVAL);
1146 kwh_cost = strtoul(s,&next, 0);
1148 err("Incomplete user parameters");
1149 return ret_err(EINVAL);
1153 while (s&& !isdigit(*s))
1156 err("Incomplete user parameters");
1157 return ret_err(EINVAL);
1161 second_tier_cost = strtoul(s,&next, 0);
1163 err("Incomplete user parameters");
1164 return ret_err(EINVAL);
1168 while (s&& !isdigit(*s))
1171 err("Incomplete user parameters");
1172 return ret_err(EINVAL);
1176 second_tier_threshold = strtoul(s,&next, 0);
1178 err("Incomplete user parameters");
1179 return ret_err(EINVAL);
1183 while (s&& !isdigit(*s))
1186 err("Incomplete user parameters");
1187 return ret_err(EINVAL);
1191 duty_cycle_threshold = strtoul(s,&next, 0);
1193 err("Incomplete user parameters");
1194 return ret_err(EINVAL);
1198 while (s&& !isdigit(*s))
1201 err("Incomplete user parameters");
1202 return ret_err(EINVAL);
1205 return wu_write_user(fd, kwh_cost, second_tier_cost,
1206 second_tier_threshold, duty_cycle_threshold);
1210 static void enable_field(char * name)
1214 for (i = 0; i< wu_num_fields; i++) {
1215 if (!strcasecmp(wu_fields[i].name, name)) {
1216 wu_fields[i].enable = 1;
1222 static void enable_all_fields(void)
1226 for (i = 0; i< wu_num_fields; i++)
1227 wu_fields[i].enable = 1;
1232 static int wu_show_help(int);
1233 static int wu_show_version(int);
1237 static int wu_store_count(int unused)
1239 char * s = wu_option_value(wu_option_count);
1243 wu_count = strtol(s,&end, 0);
1245 err("Bad count field");
1246 return ret_err(EINVAL);
1252 static int wu_store_debug(int unused)
1258 static int wu_store_delim(int unused)
1260 char * s = wu_option_value(wu_option_delim);
1267 static int wu_store_final(int unused)
1273 static int wu_store_label(int unused)
1279 static int wu_store_newline(int unused)
1285 static int wu_store_suppress(int unused)
1291 static int wu_store_localtime(int unused)
1297 static int wu_store_gmtime(int unused)
1303 static int wu_store_info_all(int unused)
1309 static int wu_store_no_data(int unused)
1315 static int wu_store_set_only(int unused)
1323 * wu_options - command line options and their associated flags
1326 static struct wu_options wu_options[] = {
1331 [wu_option_help] = {
1335 .descr = "Display help text and exit",
1336 .show = wu_show_help,
1339 [wu_option_version] = {
1340 .longopt = "version",
1343 .descr = "Display version information and exit",
1344 .show = wu_show_version,
1348 * Modifies the output for all other options
1350 [wu_option_debug] = {
1354 .descr = "Print out debugging messages",
1355 .store = wu_store_debug,
1359 * For data reading..
1361 [wu_option_count] = {
1365 .descr = "Specify number of data samples",
1367 .store = wu_store_count,
1370 [wu_option_final] = {
1374 .descr = "Print final interval information",
1375 .store = wu_store_final,
1379 * Modifies output for each option (most relevant for data)
1381 [wu_option_delim] = {
1385 .descr = "Set field delimiter (default \", \")",
1387 .store = wu_store_delim,
1390 [wu_option_newline] = {
1391 .longopt = "newline",
1394 .descr = "Use '\\n' as delimter instead",
1395 .store = wu_store_newline,
1398 [wu_option_localtime] = {
1399 .longopt = "localtime",
1402 .descr = "Print localtime with each data reading",
1403 .store = wu_store_localtime,
1406 [wu_option_gmtime] = {
1407 .longopt = "gmtime",
1410 .descr = "Print GMT time with each data reading",
1411 .store = wu_store_gmtime,
1414 [wu_option_label] = {
1418 .descr = "Show labels of each field",
1419 .store = wu_store_label,
1423 * Relevant for each of the fields below
1425 [wu_option_suppress] = {
1426 .longopt = "suppress",
1429 .descr = "Suppress printing of the field description",
1430 .store = wu_store_suppress,
1434 * These options print values from the device and exit.
1437 .longopt = "calibrate",
1440 .descr = "Print calibration parameters",
1441 .show = wu_show_cal,
1444 [wu_option_header] = {
1445 .longopt = "header",
1448 .descr = "Print data field names (as read from device)",
1449 .show = wu_show_header,
1453 * These options have an optional parameter.
1454 * W/o that parameter, they print values from the device.
1455 * W/ that parameter, they set that option and read data.
1457 * Except when the 'set-only' parameter is used, then the
1458 * parameters are set, then re-read and printed.
1460 [wu_option_interval] = {
1461 .longopt = "interval",
1464 .descr = "Get/Set sampling interval",
1466 .show = wu_show_interval,
1467 .store = wu_store_interval,
1470 [wu_option_mode] = {
1474 .descr = "Get/Set display mode",
1476 .show = wu_show_mode,
1477 .store = wu_store_mode,
1480 [wu_option_user] = {
1484 .descr = "Get/Set user parameters",
1486 .format = "<cost per kwh>,<2nd tier cost>,"
1487 "<2nd tier threshold>,"
1488 "<duty cycle threshold>",
1489 .show = wu_show_user,
1490 .store = wu_store_user,
1493 [wu_option_info_all] = {
1494 .longopt = "show-all",
1497 .descr = "Show all device parameters",
1498 .store = wu_store_info_all,
1501 [wu_option_no_data] = {
1502 .longopt = "no-data",
1505 .descr = "Don't read any data (just read device info)",
1506 .store = wu_store_no_data,
1509 [wu_option_set_only] = {
1510 .longopt = "set-only",
1513 .descr = "Set parameters only (don't read them back)",
1514 .store = wu_store_set_only,
1518 #define wu_num_options ARRAY_SIZE(wu_options)
1520 static int wu_show_version(int unused)
1522 printf("%s Version %s\n", prog_name, wu_version);
1526 static int wu_show_help(int unused)
1531 wu_show_version(unused);
1532 printf(" A program for interfacing with the Watts Up? Power Meter\n");
1535 printf("Usage: %s [<options> ... ]<device> [<values> ... ]\n",
1539 printf("<device> is the serial port the device is connected at.\n");
1542 printf("<options> are any of the following:\n");
1543 for (i = 0; i< wu_num_options; i++) {
1544 n = printf(" -%c", wu_options[i].shortopt);
1546 if (wu_options[i].param == 0)
1548 else if (wu_options[i].param == 1)
1549 n = printf(" %s", wu_options[i].option);
1550 else if (wu_options[i].param == 2)
1551 n = printf(" [%s]", wu_options[i].option);
1553 n += printf("%*c| ", n - 12, ' ');
1554 n += printf("--%s", wu_options[i].longopt);
1556 if (wu_options[i].param == 0)
1558 else if (wu_options[i].param == 1)
1559 n += printf("=%s", wu_options[i].option);
1560 else if (wu_options[i].param == 2)
1561 n += printf("[=%s]", wu_options[i].option);
1564 40 - n, ' ', wu_options[i].descr);
1567 printf("<value> specifies which of these to print out (default: ALL)\n");
1568 for (i = 0; i< wu_num_fields; i++) {
1569 printf("%12s -- %s\n", wu_fields[i].name, wu_fields[i].descr);
1577 static char * wu_option_value(unsigned int index)
1579 return (index< wu_num_options) ? wu_options[index].value : NULL;
1583 static int wu_check_option_show(int index)
1586 * Return 1 if we need to print something out for
1587 * a particular option.
1589 if (index< wu_num_options) {
1590 if (wu_options[index].flag) {
1597 static int wu_check_option_store(int index)
1600 * Return a 1 if this option is set.
1603 if (index< wu_num_options) {
1604 if (wu_options[index].flag) {
1612 static int wu_show(int index, int dev_fd)
1614 if (wu_options[index].show)
1615 return wu_options[index].show(dev_fd);
1620 * Check if the option is set, and call its method if so.
1621 * Return whether or not we did anything..
1624 static int wu_check_show(int index, int dev_fd)
1626 if (wu_check_option_show(index)) {
1627 wu_show(index, dev_fd);
1635 * Check if the option is set and if so, call it
1636 * Return the value from the ->store() method.
1639 static int wu_check_store(int index, int dev_fd)
1641 if (wu_check_option_store(index)) {
1642 if (wu_options[index].store)
1643 return wu_options[index].store(dev_fd);
1649 static void make_longopt(struct option * l)
1653 for (i = 0; i< wu_num_options; i++) {
1654 l[i].name = wu_options[i].longopt;
1655 l[i].has_arg = wu_options[i].param;
1656 l[i].flag =&wu_options[i].flag;
1661 static void make_shortopt(char * str)
1666 for (i = 0; i< wu_num_options; i++) {
1667 *s++ = wu_options[i].shortopt;
1668 if (wu_options[i].param)
1669 *s++ = wu_options[i].param == 1 ? ':' : ';';
1673 static void enable_short_option(int c, char * arg)
1678 * Friggin' getopt_long() will return the
1679 * character if we get a short option (e.g. '-h'),
1680 * instead of returning 0 like it does when it
1681 * gets a long option (e.g. "--help"). Ugh.
1683 for (i = 0; i< wu_num_options; i++) {
1684 if (wu_options[i].shortopt == c) {
1685 wu_options[i].flag = 1;
1687 wu_options[i].value = strdup(arg);
1693 static int parse_args(int argc, char ** argv)
1695 struct option longopts[wu_num_options + 1] = { };
1696 char shortopts[wu_num_options * 2] = "";
1698 make_longopt(longopts);
1699 make_shortopt(shortopts);
1706 c = getopt_long(argc, argv, shortopts,
1713 wu_options[index].flag = 1;
1715 wu_options[index].value = strdup(optarg);
1717 printf("long option: val = %c, optarg = %s\n",
1718 wu_options[index].shortopt, optarg);
1721 err("Bad parameter");
1722 return ret_err(EINVAL);
1725 enable_short_option(c, optarg);
1731 * Check for help request now and bail after
1732 * printing it, if it's set.
1734 if (wu_check_show(wu_option_help, 0))
1737 if (wu_check_show(wu_option_version, 0))
1741 * Fields to print out
1746 wu_device = argv[optind++];
1749 for (i = optind; i< argc; i++)
1750 enable_field(argv[i]);
1752 enable_all_fields();
1755 wu_show(wu_option_help, 0);
1756 return ret_err(EINVAL);
1762 int main(int argc, char ** argv)
1767 ret = parse_args(argc, argv);
1772 * Try to enable debugging early
1774 if ((ret = wu_check_store(wu_option_debug, 0)))
1777 ret = open_device(wu_device,&fd);
1781 dbg("%s: Open for business", wu_device);
1783 ret = setup_serial_device(fd);
1792 * Set delimeter before we print out any fields.
1794 if ((ret = wu_check_store(wu_option_delim, fd)))
1798 * Ditto for 'label' and 'newline' flags.
1800 if ((ret = wu_check_store(wu_option_label, fd)))
1803 if ((ret = wu_check_store(wu_option_newline, fd)))
1806 if ((ret = wu_check_store(wu_option_suppress, fd)))
1809 if ((ret = wu_check_store(wu_option_localtime, fd)))
1812 if ((ret = wu_check_store(wu_option_gmtime, fd)))
1815 if ((ret = wu_check_store(wu_option_set_only, fd)))
1818 if ((ret = wu_check_store(wu_option_no_data, fd)))
1821 if ((ret = wu_check_store(wu_option_info_all, fd)))
1826 * Options to set device parameters.
1828 if ((ret = wu_check_store(wu_option_interval, fd)))
1831 if ((ret = wu_check_store(wu_option_mode, fd)))
1834 if ((ret = wu_check_store(wu_option_user, fd)))
1838 * Check for options to print device info
1841 wu_show(wu_option_cal, fd);
1842 wu_show(wu_option_header, fd);
1843 wu_show(wu_option_interval, fd);
1844 wu_show(wu_option_mode, fd);
1845 wu_show(wu_option_user, fd);
1847 wu_check_show(wu_option_cal, fd);
1848 wu_check_show(wu_option_header, fd);
1851 wu_check_show(wu_option_interval, fd);
1852 wu_check_show(wu_option_mode, fd);
1853 wu_check_show(wu_option_user, fd);
1859 if ((ret = wu_check_store(wu_option_count, fd)))
1862 if ((ret = wu_check_store(wu_option_final, fd)))
1865 if ((ret = wu_start_log()))