sm_flukso.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /*
  2. * Copyright (c) 2010 Willem Dijkstra
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. *
  9. * - Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * - Redistributions in binary form must reproduce the above
  12. * copyright notice, this list of conditions and the following
  13. * disclaimer in the documentation and/or other materials provided
  14. * with the distribution.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  17. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  18. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  19. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  20. * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  21. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  22. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  24. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  26. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  27. * POSSIBILITY OF SUCH DAMAGE.
  28. *
  29. */
  30. /*
  31. * Get measurement data from a flukso (arduino) board tied to the serial port.
  32. *
  33. * num : value
  34. *
  35. */
  36. #include "conf.h"
  37. #include <sys/types.h>
  38. #include <sys/stat.h>
  39. #include <string.h>
  40. #include <inttypes.h>
  41. #include <fcntl.h>
  42. #include <termios.h>
  43. #include <unistd.h>
  44. #include <ctype.h>
  45. #include <strings.h>
  46. #include "error.h"
  47. #include "symon.h"
  48. #include "xmalloc.h"
  49. #define FLUKSO_MAXSENSORS 3
  50. #define FLUKSO_IDLEN 32
  51. #define SCN(x) #x
  52. static int flukso_fd = -1;
  53. static void *flukso_buf = NULL;
  54. static int flukso_size = 0;
  55. static int flukso_maxsize = 0;
  56. static int flukso_nrsensors = 0;
  57. struct flukso_sensor {
  58. char id[FLUKSO_IDLEN];
  59. uint64_t value;
  60. uint64_t n;
  61. };
  62. struct flukso_sensor flukso_sensor[FLUKSO_MAXSENSORS];
  63. void
  64. init_flukso(struct stream *st)
  65. {
  66. struct termios tio;
  67. bzero(flukso_sensor, sizeof(struct flukso_sensor) * FLUKSO_MAXSENSORS);
  68. if (flukso_buf == NULL) {
  69. flukso_maxsize = SYMON_MAX_OBJSIZE;
  70. flukso_buf = xmalloc(flukso_maxsize);
  71. }
  72. if (flukso_fd == -1) {
  73. bzero(&tio, sizeof(tio));
  74. tio.c_iflag = tio.c_oflag = tio.c_lflag = 0;
  75. tio.c_cflag = CS8 | CREAD | CLOCAL;
  76. tio.c_cc[VMIN] = 1;
  77. tio.c_cc[VTIME] = 5;
  78. if ((flukso_fd = open("/dev/ttyS0", O_RDONLY | O_NONBLOCK)) < 0)
  79. fatal("flukso: could not open '%s' for read", "/dev/ttyS0");
  80. cfsetispeed(&tio, B4800);
  81. tcsetattr(flukso_fd, TCSANOW, &tio);
  82. }
  83. if (flukso_size == 0)
  84. gets_flukso();
  85. if (st->arg != NULL &&
  86. FLUKSO_IDLEN == strspn(st->arg, "0123456789abcdef")) {
  87. bcopy(st->arg, st->parg.flukso, FLUKSO_IDLEN);
  88. info("started module flukso(%.200s)", st->arg);
  89. } else {
  90. fatal("flukso: could not parse sensor name %.200s", st->arg);
  91. }
  92. }
  93. void
  94. gets_flukso()
  95. {
  96. int len = 0;
  97. int p = 0;
  98. int i;
  99. void *nl;
  100. uint32_t value;
  101. char id[FLUKSO_IDLEN];
  102. if ((len = read(flukso_fd, flukso_buf + flukso_size, flukso_maxsize - flukso_size)) < 0) {
  103. warning("flukso: cannot read data");
  104. return;
  105. }
  106. flukso_size += len;
  107. /* We read the pwr messages rather than the pls pulse messages as we are
  108. * interested in the current load only */
  109. while ((p < flukso_size) &&
  110. ((nl = memchr(flukso_buf + p, '\n', flukso_size - p)) != NULL)) {
  111. len = nl - (flukso_buf + p) + 1;
  112. if (2 > sscanf(flukso_buf + p, "pwr %32s:%" SCNu32 "\n", &id[0], &value)) {
  113. p += len;
  114. continue;
  115. }
  116. for (i = 0; i < flukso_nrsensors; i++) {
  117. if (strncmp(flukso_sensor[i].id, id, FLUKSO_IDLEN) == 0) {
  118. flukso_sensor[i].value += value;
  119. flukso_sensor[i].n++;
  120. break;
  121. }
  122. }
  123. if ((i == flukso_nrsensors) && (flukso_nrsensors < FLUKSO_MAXSENSORS)) {
  124. bcopy(id, flukso_sensor[i].id, FLUKSO_IDLEN);
  125. flukso_sensor[i].value = value;
  126. flukso_sensor[i].n = 1;
  127. flukso_nrsensors++;
  128. }
  129. p += len;
  130. }
  131. if (p < flukso_size) {
  132. bcopy(flukso_buf + p, flukso_buf, flukso_size - p);
  133. flukso_size -= p;
  134. } else {
  135. flukso_size = 0;
  136. }
  137. }
  138. int
  139. get_flukso(char *symon_buf, int maxlen, struct stream *st)
  140. {
  141. int i;
  142. double avgwatts;
  143. for (i = 0; i < flukso_nrsensors; i++) {
  144. if (strncmp(st->parg.flukso, flukso_sensor[i].id, FLUKSO_IDLEN) == 0) {
  145. avgwatts = (double) flukso_sensor[i].value / (double) flukso_sensor[i].n;
  146. flukso_sensor[i].value = 0;
  147. flukso_sensor[i].n = 0;
  148. return snpack(symon_buf, maxlen, st->arg, MT_FLUKSO, avgwatts);
  149. }
  150. }
  151. return 0;
  152. }