summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 533dba5)
raw | patch | inline | side by side (parent: 533dba5)
author | Peter Holik <peter@holik.at> | |
Fri, 4 Aug 2006 18:37:13 +0000 (20:37 +0200) | ||
committer | Florian Forster <octo@leeloo.lan.home.verplant.org> | |
Mon, 14 Aug 2006 15:15:38 +0000 (17:15 +0200) |
I have a multimeter which can be connected to the serial port. It is
called Metex M4650CR.
No configuration is nesessary, this multimeter is autodetected on
programm start if connected and switched on. Only your serial port has
to be enabled (setserial /dev/ttyS0 autoconfig)
called Metex M4650CR.
No configuration is nesessary, this multimeter is autodetected on
programm start if connected and switched on. Only your serial port has
to be enabled (setserial /dev/ttyS0 autoconfig)
AUTHORS | patch | blob | history | |
collectd.spec | patch | blob | history | |
configure.in | patch | blob | history | |
contrib/collection.cgi | patch | blob | history | |
debian/control | patch | blob | history | |
debian/rules | patch | blob | history | |
src/Makefile.am | patch | blob | history | |
src/collectd.conf.in | patch | blob | history | |
src/multimeter.c | [new file with mode: 0644] | patch | blob |
index 7fbc7430e1041048ac4abdf820b99c6890ef525d..9a35d036a2193f2e4819aa0f93bc998101e5d16f 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
apcups plugin by:
Anthony Gialluca <tonyabg at charter.net>
-cpufreq module by:
+cpufreq and multimeter module by:
Peter Holik <peter at holik.at>
hddtemp module by:
diff --git a/collectd.spec b/collectd.spec
index e30502179cdbaacb0ea3e336837b9147c957ccbe..387763c0a33cab445eaa10c8722369c53ed8fb5b 100644 (file)
--- a/collectd.spec
+++ b/collectd.spec
%attr(0444,root,root) %{_libdir}/%{name}/hddtemp.so*
%attr(0444,root,root) %{_libdir}/%{name}/load.so*
%attr(0444,root,root) %{_libdir}/%{name}/memory.so*
+%attr(0444,root,root) %{_libdir}/%{name}/multimeter.so*
%attr(0444,root,root) %{_libdir}/%{name}/nfs.so*
%attr(0444,root,root) %{_libdir}/%{name}/ntpd.so*
%attr(0444,root,root) %{_libdir}/%{name}/ping.so*
diff --git a/configure.in b/configure.in
index 8fccc0d26b7a4fac0cc166a07eabe38ef8fe4982..6834d227460481d0c6bba47d1ec34e2a9a12f448 100644 (file)
--- a/configure.in
+++ b/configure.in
AC_COLLECTD([hddtemp], [disable], [module], [hdd temperature statistics])
AC_COLLECTD([load], [disable], [module], [system load statistics])
AC_COLLECTD([memory], [disable], [module], [memory statistics])
+AC_COLLECTD([multimeter],[disable], [module], [multimeter statistics])
AC_COLLECTD([mysql], [disable], [module], [mysql statistics])
AC_COLLECTD([nfs], [disable], [module], [nfs statistics])
AC_COLLECTD([ntpd], [disable], [module], [nfs statistics])
hddtemp . . . . . . $enable_hddtemp
load . . . . . . . $enable_load
memory . . . . . . $enable_memory
+ multimeter . . . . $enable_multimeter
mysql . . . . . . . $enable_mysql
nfs . . . . . . . . $enable_nfs
ntpd . . . . . . . $enable_ntpd
diff --git a/contrib/collection.cgi b/contrib/collection.cgi
index 29ca2d0a21a410e149f61a26c9792d362d9ecc53..a0fc4fc9b0bdfb34cbf4bc958220fcf7e9645be6 100755 (executable)
--- a/contrib/collection.cgi
+++ b/contrib/collection.cgi
'GPRINT:cpufreq_max:MAX:%5.1lf%s Max,',
'GPRINT:cpufreq_avg:LAST:%5.1lf%s Last\l'
],
+ multimeter => [
+ 'DEF:multimeter_avg={file}:value:AVERAGE',
+ 'DEF:multimeter_min={file}:value:MIN',
+ 'DEF:multimeter_max={file}:value:MAX',
+ "AREA:multimeter_max#$HalfBlue",
+ "AREA:multimeter_min#$Canvas",
+ "LINE1:multimeter_avg#$FullBlue:Multimeter",
+ 'GPRINT:multimeter_min:MIN:%4.1lf Min,',
+ 'GPRINT:multimeter_avg:AVERAGE:%4.1lf Average,',
+ 'GPRINT:multimeter_max:MAX:%4.1lf Max,',
+ 'GPRINT:multimeter_avg:LAST:%4.1lf Last\l'
+ ],
users => [
'DEF:users_avg={file}:users:AVERAGE',
'DEF:users_min={file}:users:MIN',
time_dispersion => ['-t', 'NTPd time dispersion ({inst})', '-v', 'Seconds'],
traffic => ['-t', '{host} {inst} traffic', '-v', 'Bit/s'],
users => ['-t', '{host} users', '-v', 'Users'],
+ multimeter => ['-t', '{host} multimeter', '-v', 'Value'],
voltage => ['-t', '{host} voltage', '-v', 'Volts'],
vs_threads => ['-t', '{host} threads', '-v', 'Threads'],
vs_memory => ['-t', '{host} memory usage', '-v', 'Bytes'],
ping => \&output_graph_ping,
sensors => 1,
traffic => 1,
- users => 1
+ users => 1,
+ multimeter => 1
};
our @Info;
diff --git a/debian/control b/debian/control
index 3ee102e44d5017fe929c475119189872988dbe11..9c0e11b4f42ad91dfcd6f986b8ef3b1fde3e251c 100644 (file)
--- a/debian/control
+++ b/debian/control
Depends: collectd (= ${Source-Version}), libsensors3
Description: collectd module for libsensors.
collectd module to collect system temperatures.
+
+Package: collectd-multimeter
+Architecture: any
+Depends: collectd (= ${Source-Version}), ${shlibs:Depends}
+Description: statistics collection daemon (multimeter plugin)
+ collectd is a small daemon written in C for performance. It reads various
+ system statistics and updates RRD files, creating them if necessary. Since
+ the daemon doesn't need to startup every time it wants to update the files
+ it's very fast and easy on the system. Also, the statistics are very fine
+ grained since the files are updated every 10 seconds.
+ .
+ This package contains the multimeter plugin which collects values from a
+ multimeter connected to a serial port.
diff --git a/debian/rules b/debian/rules
index de41de1871a07ecdca27b19fad2bc9cf035d5f2f..1575a821e0441c478e0e8fe36f537ee4f144025b 100755 (executable)
--- a/debian/rules
+++ b/debian/rules
CFLAGS = -Wall -g
-PLUGINS = apache mysql sensors
+PLUGINS = apache mysql sensors multimeter
ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
CFLAGS += -O0
diff --git a/src/Makefile.am b/src/Makefile.am
index 46d1a69cc38108feb285434d74e3dddf0d1dffa3..5538f64174b1507edbb99bbb09ba53ca3e356513 100644 (file)
--- a/src/Makefile.am
+++ b/src/Makefile.am
endif
endif
+if BUILD_MODULE_MULTIMETER
+pkglib_LTLIBRARIES += multimeter.la
+multimeter_la_SOURCES = multimeter.c
+multimeter_la_LDFLAGS = -module -avoid-version
+collectd_LDADD += "-dlopen" multimeter.la
+collectd_DEPENDENCIES += multimeter.la
+endif
+
if BUILD_MODULE_MYSQL
pkglib_LTLIBRARIES += mysql.la
mysql_la_SOURCES = mysql.c
diff --git a/src/collectd.conf.in b/src/collectd.conf.in
index 5e894de5a31c7023e8ea5fbe97de1d5e367ed686..29035abf72d43b4bcf69dbff608f3346ef4059b3 100644 (file)
--- a/src/collectd.conf.in
+++ b/src/collectd.conf.in
@BUILD_MODULE_HDDTEMP_TRUE@LoadPlugin hddtemp
@BUILD_MODULE_LOAD_TRUE@LoadPlugin load
@BUILD_MODULE_MEMORY_TRUE@LoadPlugin memory
+@BUILD_MODULE_MULTIMETER_TRUE@LoadPlugin multimeter
@BUILD_MODULE_MYSQL_TRUE@LoadPlugin mysql
@BUILD_MODULE_NFS_TRUE@LoadPlugin nfs
@BUILD_MODULE_NTPD_TRUE@LoadPlugin ntpd
diff --git a/src/multimeter.c b/src/multimeter.c
--- /dev/null
+++ b/src/multimeter.c
@@ -0,0 +1,234 @@
+/**
+ * collectd - src/multimeter.c
+ * Copyright (C) 2005,2006 Peter Holik
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Peter Holik <peter at holik.at>
+ *
+ * Used multimeter: Metex M-4650CR
+ *
+ **/
+
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <math.h>
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#define MODULE_NAME "multimeter"
+
+static char *multimeter_file = "multimeter.rrd";
+
+static char *ds_def[] =
+{
+ "DS:value:GAUGE:"COLLECTD_HEARTBEAT":U:U",
+ NULL
+};
+static int ds_num = 1;
+
+static int fd = -1;
+
+static int multimeter_timeval_sub (struct timeval *tv1, struct timeval *tv2,
+ struct timeval *res)
+{
+ if ((tv1->tv_sec < tv2->tv_sec) ||
+ ((tv1->tv_sec == tv2->tv_sec) && (tv1->tv_usec < tv2->tv_usec)))
+ return (-1);
+
+ res->tv_sec = tv1->tv_sec - tv2->tv_sec;
+ res->tv_usec = tv1->tv_usec - tv2->tv_usec;
+
+ assert ((res->tv_sec > 0) || ((res->tv_sec == 0) && (res->tv_usec > 0)));
+
+ while (res->tv_usec < 0)
+ {
+ res->tv_usec += 1000000;
+ res->tv_sec--;
+ }
+ return (0);
+}
+#define LINE_LENGTH 14
+static int multimeter_read_value(double *value)
+{
+ int retry = 3; /* sometimes we receive garbadge */
+
+ do
+ {
+ struct timeval time_end;
+
+ tcflush(fd, TCIFLUSH);
+
+ if (gettimeofday (&time_end, NULL) < 0)
+ {
+ syslog (LOG_ERR, MODULE_NAME": gettimeofday failed: %s",
+ strerror (errno));
+ return (-1);
+ }
+ time_end.tv_sec++;
+
+ while (1)
+ {
+ char buf[LINE_LENGTH];
+ char *range;
+ int status;
+ fd_set rfds;
+ struct timeval timeout;
+ struct timeval time_now;
+
+ write(fd, "D", 1);
+
+ FD_ZERO(&rfds);
+ FD_SET(fd, &rfds);
+
+ if (gettimeofday (&time_now, NULL) < 0)
+ {
+ syslog (LOG_ERR, MODULE_NAME": gettimeofday failed: %s",
+ strerror (errno));
+ return (-1);
+ }
+ if (multimeter_timeval_sub (&time_end, &time_now, &timeout) == -1)
+ break;
+
+ status = select(fd+1, &rfds, NULL, NULL, &timeout);
+
+ if (status > 0) /* usually we succeed */
+ {
+ status = read(fd, buf, LINE_LENGTH);
+
+ if ((status < 0) && ((errno == EAGAIN) || (errno == EINTR)))
+ continue;
+
+ /* Format: "DC 00.000mV \r" */
+ if (status > 0 && status == LINE_LENGTH)
+ {
+ *value = strtod(buf + 2, &range);
+
+ if ( range > (buf + 6) )
+ {
+ range = buf + 9;
+
+ switch ( *range )
+ {
+ case 'p': *value *= 1.0E-12; break;
+ case 'n': *value *= 1.0E-9; break;
+ case 'u': *value *= 1.0E-6; break;
+ case 'm': *value *= 1.0E-3; break;
+ case 'k': *value *= 1.0E3; break;
+ case 'M': *value *= 1.0E6; break;
+ case 'G': *value *= 1.0E9; break;
+ }
+ }
+ else
+ return (-1); /* Overflow */
+
+ return (0); /* value received */
+ }
+ else break;
+ }
+ else if (!status) /* Timeout */
+ {
+ break;
+ }
+ else if ((status == -1) && ((errno == EAGAIN) || (errno == EINTR)))
+ {
+ continue;
+ }
+ else /* status == -1 */
+ {
+ syslog (LOG_ERR, MODULE_NAME": select failed: %s",
+ strerror (errno));
+ break;
+ }
+ }
+ } while (--retry);
+
+ return (-2); /* no value received */
+}
+
+static void multimeter_init (void)
+{
+ int i;
+ char device[] = "/dev/ttyS ";
+
+ for (i = 0; i < 10; i++)
+ {
+ device[strlen(device)-1] = i + '0';
+
+ if ((fd = open(device, O_RDWR | O_NOCTTY)) > 0)
+ {
+ struct termios tios;
+ int rts = TIOCM_RTS;
+ double value;
+
+ tios.c_cflag = B1200 | CS7 | CSTOPB | CREAD | CLOCAL;
+ tios.c_iflag = IGNBRK | IGNPAR;
+ tios.c_oflag = 0;
+ tios.c_lflag = 0;
+ tios.c_cc[VTIME] = 3;
+ tios.c_cc[VMIN] = LINE_LENGTH;
+
+ tcflush(fd, TCIFLUSH);
+ tcsetattr(fd, TCSANOW, &tios);
+ ioctl(fd, TIOCMBIC, &rts);
+
+ if (multimeter_read_value(&value) < -1)
+ {
+ close(fd);
+ fd = -1;
+ }
+ else
+ {
+ syslog (LOG_INFO, MODULE_NAME" found (%s)", device);
+ return;
+ }
+ }
+ }
+ syslog (LOG_ERR, MODULE_NAME" not found");
+}
+#undef LINE_LENGTH
+
+static void multimeter_write (char *host, char *inst, char *val)
+{
+ rrd_update_file (host, multimeter_file, val, ds_def, ds_num);
+}
+#define BUFSIZE 128
+static void multimeter_submit (double *value)
+{
+ char buf[BUFSIZE];
+
+ if (snprintf (buf, BUFSIZE, "%u:%f", (unsigned int) curtime, *value) >= BUFSIZE)
+ return;
+
+ plugin_submit (MODULE_NAME, NULL, buf);
+}
+#undef BUFSIZE
+
+static void multimeter_read (void)
+{
+ double value;
+
+ if (fd > -1 && !(multimeter_read_value(&value)))
+ multimeter_submit (&value);
+}
+
+void module_register (void)
+{
+ plugin_register (MODULE_NAME, multimeter_init, multimeter_read, multimeter_write);
+}
+
+#undef MODULE_NAME