main.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /*
  2. * Multimeter measurement
  3. *
  4. * Copyright (C) 2016-2018 Michael Buesch <m@bues.ch>
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. */
  16. #include "es51984.h"
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <errno.h>
  21. #include <stdint.h>
  22. #include <stdbool.h>
  23. #include <getopt.h>
  24. #include <time.h>
  25. #include <sys/time.h>
  26. #include <math.h>
  27. static struct {
  28. const char *dev;
  29. bool csv;
  30. bool timestamp;
  31. double sleep;
  32. } cmdline;
  33. static int timeval_msec_diff(const struct timeval *a, const struct timeval *b)
  34. {
  35. int64_t usec_a, usec_b, usec_diff;
  36. usec_a = (int64_t)a->tv_sec * 1000000;
  37. usec_a += (int64_t)a->tv_usec;
  38. usec_b = (int64_t)b->tv_sec * 1000000;
  39. usec_b += (int64_t)b->tv_usec;
  40. usec_diff = usec_a - usec_b;
  41. return usec_diff / 1000;
  42. }
  43. static int dump_es51984(enum es51984_board_type board,
  44. const char *dev,
  45. bool csv,
  46. bool timestamp,
  47. double sleep)
  48. {
  49. struct es51984 *es = NULL;
  50. struct es51984_sample sample;
  51. int ret = -ENODEV;
  52. int err;
  53. const char *units;
  54. double value;
  55. time_t t;
  56. struct tm tm;
  57. char tbuf[256];
  58. struct timeval tv, prev_tv = { 0 };
  59. int sleep_ms;
  60. bool firstrun = true;
  61. sleep_ms = (int)round(sleep * 1000.0);
  62. es = es51984_init(board, dev);
  63. if (!es)
  64. goto out;
  65. err = es51984_sync(es);
  66. if (err) {
  67. fprintf(stderr, "Failed to sync to data stream.\n");
  68. goto out;
  69. }
  70. /* Discard first sample */
  71. err = es51984_get_sample(es, &sample, 1, 0);
  72. if (err) {
  73. fprintf(stderr, "ERROR: Failed to read sample.\n");
  74. goto out;
  75. }
  76. if (gettimeofday(&prev_tv, NULL)) {
  77. fprintf(stderr, "ERROR: gettimeofday() failed.\n");
  78. goto out;
  79. }
  80. while (1) {
  81. err = es51984_get_sample(es, &sample, 1, 0);
  82. if (err) {
  83. fprintf(stderr, "ERROR: Failed to read sample.\n");
  84. continue;
  85. }
  86. t = time(NULL);
  87. if (t == ((time_t)-1)) {
  88. fprintf(stderr, "ERROR: Failed to get time.\n");
  89. continue;
  90. }
  91. if (sleep_ms > 0) {
  92. if (gettimeofday(&tv, NULL)) {
  93. fprintf(stderr, "ERROR: gettimeofday() failed.\n");
  94. continue;
  95. }
  96. if ((timeval_msec_diff(&tv, &prev_tv) < sleep_ms) && !firstrun)
  97. continue;
  98. prev_tv = tv;
  99. }
  100. localtime_r(&t, &tm);
  101. strftime(tbuf, sizeof(tbuf), "%F;%T", &tm);
  102. if (sample.function == ES51984_FUNC_TEMP)
  103. units = sample.degree ? "*C" : "F";
  104. else
  105. units = es51984_get_units(&sample);
  106. value = sample.overflow ? 0.0 : sample.value;
  107. if (csv) {
  108. printf("%s%s%lf\n",
  109. timestamp ? tbuf : "",
  110. timestamp ? ";" : "",
  111. value);
  112. } else {
  113. printf("%s%s%s%.3lf %s%s (%s, %s, %s)%s\n",
  114. timestamp ? "[" : "",
  115. timestamp ? tbuf : "",
  116. timestamp ? "] " : "",
  117. value,
  118. sample.overflow ? "OVERFLOW " : "",
  119. units,
  120. sample.dc_mode ? "DC" : "AC",
  121. sample.auto_mode ? "auto" : "man",
  122. sample.hold ? "hold" : "no-hold",
  123. sample.batt_low ? " BATTERY LOW" : "");
  124. }
  125. fflush(stdout);
  126. firstrun = false;
  127. }
  128. ret = 0;
  129. out:
  130. es51984_exit(es);
  131. return ret;
  132. }
  133. static void usage(void)
  134. {
  135. printf("Multimeter measurement\n\n"
  136. " Usage: mmmeas [OPTIONS] DEVICE\n"
  137. "\n"
  138. " DEVICE is the serial device node.\n"
  139. "\n"
  140. "Options:\n"
  141. " -c|--csv Use CSV output\n"
  142. " -t|--timestamp Print time stamps in output\n"
  143. " -s|--sleep SECONDS Sleep and discard values between prints\n"
  144. " -h|--help Print this help text\n"
  145. );
  146. }
  147. static int parse_args(int argc, char **argv)
  148. {
  149. static const struct option long_options[] = {
  150. { "csv", no_argument, NULL, 'c', },
  151. { "timestamp", no_argument, NULL, 't', },
  152. { "sleep", required_argument, NULL, 's', },
  153. { "help", no_argument, NULL, 'h', },
  154. { NULL, },
  155. };
  156. int c, idx;
  157. cmdline.dev = NULL;
  158. cmdline.csv = false;
  159. cmdline.timestamp = false;
  160. cmdline.sleep = 0.0;
  161. while (1) {
  162. c = getopt_long(argc, argv, "cts:h",
  163. long_options, &idx);
  164. if (c == -1)
  165. break;
  166. switch (c) {
  167. case 'c':
  168. cmdline.csv = true;
  169. break;
  170. case 't':
  171. cmdline.timestamp = true;
  172. break;
  173. case 's':
  174. if (sscanf(optarg, "%lf", &cmdline.sleep) != 1) {
  175. fprintf(stderr, "ERROR: Invalid --sleep value\n");
  176. return -1;
  177. }
  178. break;
  179. case 'h':
  180. usage();
  181. return 1;
  182. default:
  183. return -1;
  184. }
  185. }
  186. if (optind < argc)
  187. cmdline.dev = argv[optind++];
  188. if (optind < argc) {
  189. fprintf(stderr, "ERROR: Too many arguments\n\n");
  190. usage();
  191. return -1;
  192. }
  193. if (!cmdline.dev) {
  194. fprintf(stderr, "ERROR: DEVICE node missing\n\n");
  195. usage();
  196. return -1;
  197. }
  198. return 0;
  199. }
  200. int main(int argc, char **argv)
  201. {
  202. int ret = 1;
  203. int err;
  204. err = parse_args(argc, argv);
  205. if (err > 0)
  206. ret = 0;
  207. if (err)
  208. goto out;
  209. err = dump_es51984(ES51984_BOARD_AMPROBE_35XPA,
  210. cmdline.dev,
  211. cmdline.csv,
  212. cmdline.timestamp,
  213. cmdline.sleep);
  214. if (err)
  215. goto out;
  216. ret = 0;
  217. out:
  218. return ret;
  219. }