collectd: backport modbus improvements
* 938897a2 Add scale and shift to modbus plugin * 60280b80 correcting all the wrongs * a00ab529 Add support for RS485 to modbus plugin Signed-off-by: Daniel Golle <daniel@makrotopia.org>
This commit is contained in:
parent
56f71a8623
commit
f70364df8b
4 changed files with 316 additions and 1 deletions
|
@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=collectd
|
PKG_NAME:=collectd
|
||||||
PKG_VERSION:=5.8.1
|
PKG_VERSION:=5.8.1
|
||||||
PKG_RELEASE:=3
|
PKG_RELEASE:=4
|
||||||
|
|
||||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
|
||||||
PKG_SOURCE_URL:=https://collectd.org/files/ \
|
PKG_SOURCE_URL:=https://collectd.org/files/ \
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
From eeabc41e703f39cae0ad7eb8a596045a5a2f25b4 Mon Sep 17 00:00:00 2001
|
||||||
|
From: cekstam <christian.ekstam@gmail.com>
|
||||||
|
Date: Tue, 27 Mar 2018 13:15:28 +0200
|
||||||
|
Subject: [PATCH 1/3] Add scale and shift to modbus plugin
|
||||||
|
|
||||||
|
Adding a Scale and Shift parameter to the modbus plugin in order to correct amplifed data
|
||||||
|
---
|
||||||
|
src/collectd.conf.pod | 10 ++++++++++
|
||||||
|
src/modbus.c | 18 ++++++++++++++----
|
||||||
|
2 files changed, 24 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
--- a/src/collectd.conf.pod
|
||||||
|
+++ b/src/collectd.conf.pod
|
||||||
|
@@ -4169,6 +4169,16 @@ supported.
|
||||||
|
Sets the type instance to use when dispatching the value to I<collectd>. If
|
||||||
|
unset, an empty string (no type instance) is used.
|
||||||
|
|
||||||
|
+=item B<Scale> I<Value>
|
||||||
|
+
|
||||||
|
+The values taken from collectd are multiplied by I<Value>. The field is optional
|
||||||
|
+and the default is B<1.0>.
|
||||||
|
+
|
||||||
|
+=item B<Shift> I<Value>
|
||||||
|
+
|
||||||
|
+I<Value> is added to values from collectd after they have been multiplied by
|
||||||
|
+B<Scale> value. The field is optional and the default value is B<0.0>.
|
||||||
|
+
|
||||||
|
=back
|
||||||
|
|
||||||
|
=item E<lt>B<Host> I<Name>E<gt> blocks
|
||||||
|
--- a/src/modbus.c
|
||||||
|
+++ b/src/modbus.c
|
||||||
|
@@ -105,6 +105,8 @@ struct mb_data_s /* {{{ */
|
||||||
|
mb_mreg_type_t modbus_register_type;
|
||||||
|
char type[DATA_MAX_NAME_LEN];
|
||||||
|
char instance[DATA_MAX_NAME_LEN];
|
||||||
|
+ double scale;
|
||||||
|
+ double shift;
|
||||||
|
|
||||||
|
mb_data_t *next;
|
||||||
|
}; /* }}} */
|
||||||
|
@@ -395,13 +397,13 @@ static int mb_init_connection(mb_host_t
|
||||||
|
#define CAST_TO_VALUE_T(ds, vt, raw) \
|
||||||
|
do { \
|
||||||
|
if ((ds)->ds[0].type == DS_TYPE_COUNTER) \
|
||||||
|
- (vt).counter = (counter_t)(raw); \
|
||||||
|
+ (vt).counter = (((counter_t)(raw) * ds[0].scale) + ds[0].shift); \
|
||||||
|
else if ((ds)->ds[0].type == DS_TYPE_GAUGE) \
|
||||||
|
- (vt).gauge = (gauge_t)(raw); \
|
||||||
|
+ (vt).gauge = (((gauge_t)(raw) * ds[0].scale) + ds[0].shift); \
|
||||||
|
else if ((ds)->ds[0].type == DS_TYPE_DERIVE) \
|
||||||
|
- (vt).derive = (derive_t)(raw); \
|
||||||
|
+ (vt).derive = (((derive_t)(raw) * ds[0].scale) + ds[0].shift); \
|
||||||
|
else /* if (ds->ds[0].type == DS_TYPE_ABSOLUTE) */ \
|
||||||
|
- (vt).absolute = (absolute_t)(raw); \
|
||||||
|
+ (vt).absolute = (((absolute_t)(raw) * ds[0].scale) + ds[0].shift); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */
|
||||||
|
@@ -723,6 +725,8 @@ static int mb_config_add_data(oconfig_it
|
||||||
|
data.name = NULL;
|
||||||
|
data.register_type = REG_TYPE_UINT16;
|
||||||
|
data.next = NULL;
|
||||||
|
+ data.scale = 1;
|
||||||
|
+ data.shift = 0;
|
||||||
|
|
||||||
|
status = cf_util_get_string(ci, &data.name);
|
||||||
|
if (status != 0)
|
||||||
|
@@ -736,6 +740,12 @@ static int mb_config_add_data(oconfig_it
|
||||||
|
else if (strcasecmp("Instance", child->key) == 0)
|
||||||
|
status = cf_util_get_string_buffer(child, data.instance,
|
||||||
|
sizeof(data.instance));
|
||||||
|
+ else if (strcasecmp("Scale", child->key) == 0)
|
||||||
|
+ status = cf_util_get_string_buffer(child, data.scale,
|
||||||
|
+ sizeof(data.scale));
|
||||||
|
+ else if (strcasecmp("Shift", child->key) == 0)
|
||||||
|
+ status = cf_util_get_string_buffer(child, data.shift,
|
||||||
|
+ sizeof(data.shift));
|
||||||
|
else if (strcasecmp("RegisterBase", child->key) == 0)
|
||||||
|
status = cf_util_get_int(child, &data.register_base);
|
||||||
|
else if (strcasecmp("RegisterType", child->key) == 0) {
|
120
utils/collectd/patches/052-correcting-all-the-wrongs.patch
Normal file
120
utils/collectd/patches/052-correcting-all-the-wrongs.patch
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
From e596496f5c783f4bba85c4d559502c98e4050465 Mon Sep 17 00:00:00 2001
|
||||||
|
From: cekstam <christian.ekstam@gmail.com>
|
||||||
|
Date: Tue, 27 Mar 2018 14:11:52 +0200
|
||||||
|
Subject: [PATCH 2/3] correcting all the wrongs
|
||||||
|
|
||||||
|
, data->scale, data->shift
|
||||||
|
---
|
||||||
|
src/modbus.c | 32 +++++++++++++++-----------------
|
||||||
|
1 file changed, 15 insertions(+), 17 deletions(-)
|
||||||
|
|
||||||
|
--- a/src/modbus.c
|
||||||
|
+++ b/src/modbus.c
|
||||||
|
@@ -394,16 +394,16 @@ static int mb_init_connection(mb_host_t
|
||||||
|
} /* }}} int mb_init_connection */
|
||||||
|
#endif /* !LEGACY_LIBMODBUS */
|
||||||
|
|
||||||
|
-#define CAST_TO_VALUE_T(ds, vt, raw) \
|
||||||
|
+#define CAST_TO_VALUE_T(ds, vt, raw, scale, shift) \
|
||||||
|
do { \
|
||||||
|
if ((ds)->ds[0].type == DS_TYPE_COUNTER) \
|
||||||
|
- (vt).counter = (((counter_t)(raw) * ds[0].scale) + ds[0].shift); \
|
||||||
|
+ (vt).counter = (((counter_t)(raw) * scale) + shift); \
|
||||||
|
else if ((ds)->ds[0].type == DS_TYPE_GAUGE) \
|
||||||
|
- (vt).gauge = (((gauge_t)(raw) * ds[0].scale) + ds[0].shift); \
|
||||||
|
+ (vt).gauge = (((gauge_t)(raw) * scale) + shift); \
|
||||||
|
else if ((ds)->ds[0].type == DS_TYPE_DERIVE) \
|
||||||
|
- (vt).derive = (((derive_t)(raw) * ds[0].scale) + ds[0].shift); \
|
||||||
|
+ (vt).derive = (((derive_t)(raw) * scale) + shift); \
|
||||||
|
else /* if (ds->ds[0].type == DS_TYPE_ABSOLUTE) */ \
|
||||||
|
- (vt).absolute = (((absolute_t)(raw) * ds[0].scale) + ds[0].shift); \
|
||||||
|
+ (vt).absolute = (((absolute_t)(raw) * scale) + shift); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */
|
||||||
|
@@ -532,7 +532,7 @@ static int mb_read_data(mb_host_t *host,
|
||||||
|
"Returned float value is %g",
|
||||||
|
(double)float_value);
|
||||||
|
|
||||||
|
- CAST_TO_VALUE_T(ds, vt, float_value);
|
||||||
|
+ CAST_TO_VALUE_T(ds, vt, float_value, data->scale, data->shift);
|
||||||
|
mb_submit(host, slave, data, vt);
|
||||||
|
} else if (data->register_type == REG_TYPE_FLOAT_CDAB) {
|
||||||
|
float float_value;
|
||||||
|
@@ -543,7 +543,7 @@ static int mb_read_data(mb_host_t *host,
|
||||||
|
"Returned float value is %g",
|
||||||
|
(double)float_value);
|
||||||
|
|
||||||
|
- CAST_TO_VALUE_T(ds, vt, float_value);
|
||||||
|
+ CAST_TO_VALUE_T(ds, vt, float_value, data->scale, data->shift);
|
||||||
|
mb_submit(host, slave, data, vt);
|
||||||
|
} else if (data->register_type == REG_TYPE_INT32) {
|
||||||
|
union {
|
||||||
|
@@ -557,7 +557,7 @@ static int mb_read_data(mb_host_t *host,
|
||||||
|
"Returned int32 value is %" PRIi32,
|
||||||
|
v.i32);
|
||||||
|
|
||||||
|
- CAST_TO_VALUE_T(ds, vt, v.i32);
|
||||||
|
+ CAST_TO_VALUE_T(ds, vt, v.i32, data->scale, data->shift);
|
||||||
|
mb_submit(host, slave, data, vt);
|
||||||
|
} else if (data->register_type == REG_TYPE_INT32_CDAB) {
|
||||||
|
union {
|
||||||
|
@@ -571,7 +571,7 @@ static int mb_read_data(mb_host_t *host,
|
||||||
|
"Returned int32 value is %" PRIi32,
|
||||||
|
v.i32);
|
||||||
|
|
||||||
|
- CAST_TO_VALUE_T(ds, vt, v.i32);
|
||||||
|
+ CAST_TO_VALUE_T(ds, vt, v.i32, data->scale, data->shift);
|
||||||
|
mb_submit(host, slave, data, vt);
|
||||||
|
} else if (data->register_type == REG_TYPE_INT16) {
|
||||||
|
union {
|
||||||
|
@@ -586,7 +586,7 @@ static int mb_read_data(mb_host_t *host,
|
||||||
|
"Returned int16 value is %" PRIi16,
|
||||||
|
v.i16);
|
||||||
|
|
||||||
|
- CAST_TO_VALUE_T(ds, vt, v.i16);
|
||||||
|
+ CAST_TO_VALUE_T(ds, vt, v.i16, data->scale, data->shift);
|
||||||
|
mb_submit(host, slave, data, vt);
|
||||||
|
} else if (data->register_type == REG_TYPE_UINT32) {
|
||||||
|
uint32_t v32;
|
||||||
|
@@ -597,7 +597,7 @@ static int mb_read_data(mb_host_t *host,
|
||||||
|
"Returned uint32 value is %" PRIu32,
|
||||||
|
v32);
|
||||||
|
|
||||||
|
- CAST_TO_VALUE_T(ds, vt, v32);
|
||||||
|
+ CAST_TO_VALUE_T(ds, vt, v32, data->scale, data->shift);
|
||||||
|
mb_submit(host, slave, data, vt);
|
||||||
|
} else if (data->register_type == REG_TYPE_UINT32_CDAB) {
|
||||||
|
uint32_t v32;
|
||||||
|
@@ -608,7 +608,7 @@ static int mb_read_data(mb_host_t *host,
|
||||||
|
"Returned uint32 value is %" PRIu32,
|
||||||
|
v32);
|
||||||
|
|
||||||
|
- CAST_TO_VALUE_T(ds, vt, v32);
|
||||||
|
+ CAST_TO_VALUE_T(ds, vt, v32, data->scale, data->shift);
|
||||||
|
mb_submit(host, slave, data, vt);
|
||||||
|
} else /* if (data->register_type == REG_TYPE_UINT16) */
|
||||||
|
{
|
||||||
|
@@ -618,7 +618,7 @@ static int mb_read_data(mb_host_t *host,
|
||||||
|
"Returned uint16 value is %" PRIu16,
|
||||||
|
values[0]);
|
||||||
|
|
||||||
|
- CAST_TO_VALUE_T(ds, vt, values[0]);
|
||||||
|
+ CAST_TO_VALUE_T(ds, vt, values[0], data->scale, data->shift);
|
||||||
|
mb_submit(host, slave, data, vt);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -741,11 +741,9 @@ static int mb_config_add_data(oconfig_it
|
||||||
|
status = cf_util_get_string_buffer(child, data.instance,
|
||||||
|
sizeof(data.instance));
|
||||||
|
else if (strcasecmp("Scale", child->key) == 0)
|
||||||
|
- status = cf_util_get_string_buffer(child, data.scale,
|
||||||
|
- sizeof(data.scale));
|
||||||
|
+ status = cf_util_get_double(child, &data.scale);
|
||||||
|
else if (strcasecmp("Shift", child->key) == 0)
|
||||||
|
- status = cf_util_get_string_buffer(child, data.shift,
|
||||||
|
- sizeof(data.shift));
|
||||||
|
+ status = cf_util_get_double(child, &data.shift);
|
||||||
|
else if (strcasecmp("RegisterBase", child->key) == 0)
|
||||||
|
status = cf_util_get_int(child, &data.register_base);
|
||||||
|
else if (strcasecmp("RegisterType", child->key) == 0) {
|
|
@ -0,0 +1,114 @@
|
||||||
|
From a00ab52931a587cf29c53a945e9295b4d7fe41ba Mon Sep 17 00:00:00 2001
|
||||||
|
From: Daniel Golle <daniel@makrotopia.org>
|
||||||
|
Date: Thu, 28 Mar 2019 01:52:04 +0100
|
||||||
|
Subject: [PATCH] Add support for RS485 to modbus plugin
|
||||||
|
|
||||||
|
Allow setting up RS485 mode for Modbus-RTU
|
||||||
|
---
|
||||||
|
src/collectd.conf.pod | 6 +++++
|
||||||
|
src/modbus.c | 55 +++++++++++++++++++++++++++++++++++++++----
|
||||||
|
2 files changed, 57 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
--- a/src/collectd.conf.pod
|
||||||
|
+++ b/src/collectd.conf.pod
|
||||||
|
@@ -4234,6 +4234,12 @@ For Modbus/RTU, specifies the path to th
|
||||||
|
For Modbus/RTU, specifies the baud rate of the serial device.
|
||||||
|
Note, connections currently support only 8/N/1.
|
||||||
|
|
||||||
|
+=item B<UARTType> I<UARTType>
|
||||||
|
+
|
||||||
|
+For Modbus/RTU, specifies the type of the serial device.
|
||||||
|
+RS232, RS422 and RS485 are supported. Defaults to RS232.
|
||||||
|
+Available only on Linux systems with libmodbus>=2.9.4.
|
||||||
|
+
|
||||||
|
=item B<Interval> I<Interval>
|
||||||
|
|
||||||
|
Sets the interval (in seconds) in which the values will be collected from this
|
||||||
|
--- a/src/modbus.c
|
||||||
|
+++ b/src/modbus.c
|
||||||
|
@@ -95,6 +95,12 @@ enum mb_conntype_e /* {{{ */
|
||||||
|
MBCONN_RTU }; /* }}} */
|
||||||
|
typedef enum mb_conntype_e mb_conntype_t;
|
||||||
|
|
||||||
|
+enum mb_uarttype_e /* {{{ */
|
||||||
|
+{ UARTTYPE_RS232,
|
||||||
|
+ UARTTYPE_RS422,
|
||||||
|
+ UARTTYPE_RS485 }; /* }}} */
|
||||||
|
+typedef enum mb_uarttype_e mb_uarttype_t;
|
||||||
|
+
|
||||||
|
struct mb_data_s;
|
||||||
|
typedef struct mb_data_s mb_data_t;
|
||||||
|
struct mb_data_s /* {{{ */
|
||||||
|
@@ -124,8 +130,9 @@ struct mb_host_s /* {{{ */
|
||||||
|
char host[DATA_MAX_NAME_LEN];
|
||||||
|
char node[NI_MAXHOST]; /* TCP hostname or RTU serial device */
|
||||||
|
/* char service[NI_MAXSERV]; */
|
||||||
|
- int port; /* for Modbus/TCP */
|
||||||
|
- int baudrate; /* for Modbus/RTU */
|
||||||
|
+ int port; /* for Modbus/TCP */
|
||||||
|
+ int baudrate; /* for Modbus/RTU */
|
||||||
|
+ mb_uarttype_t uarttype; /* UART type for Modbus/RTU */
|
||||||
|
mb_conntype_t conntype;
|
||||||
|
cdtime_t interval;
|
||||||
|
|
||||||
|
@@ -390,6 +397,22 @@ static int mb_init_connection(mb_host_t
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
+#if defined(linux) && LIBMODBUS_VERSION_CHECK(2, 9, 4)
|
||||||
|
+ switch (host->uarttype) {
|
||||||
|
+ case UARTTYPE_RS485:
|
||||||
|
+ if (modbus_rtu_set_serial_mode(host->connection, MODBUS_RTU_RS485))
|
||||||
|
+ DEBUG("Modbus plugin: Setting RS485 mode failed.");
|
||||||
|
+ break;
|
||||||
|
+ case UARTTYPE_RS422:
|
||||||
|
+ /* libmodbus doesn't say anything about full-duplex symmetric RS422 UART */
|
||||||
|
+ break;
|
||||||
|
+ case UARTTYPE_RS232:
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ DEBUG("Modbus plugin: Invalid UART type!.");
|
||||||
|
+ }
|
||||||
|
+#endif /* defined(linux) && LIBMODBUS_VERSION_CHECK(2, 9, 4) */
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
} /* }}} int mb_init_connection */
|
||||||
|
#endif /* !LEGACY_LIBMODBUS */
|
||||||
|
@@ -951,11 +974,35 @@ static int mb_config_add_host(oconfig_it
|
||||||
|
status = -1;
|
||||||
|
} else if (strcasecmp("Device", child->key) == 0) {
|
||||||
|
status = cf_util_get_string_buffer(child, host->node, sizeof(host->node));
|
||||||
|
- if (status == 0)
|
||||||
|
+ if (status == 0) {
|
||||||
|
host->conntype = MBCONN_RTU;
|
||||||
|
+ host->uarttype = UARTTYPE_RS232;
|
||||||
|
+ }
|
||||||
|
} else if (strcasecmp("Baudrate", child->key) == 0)
|
||||||
|
status = cf_util_get_int(child, &host->baudrate);
|
||||||
|
- else if (strcasecmp("Interval", child->key) == 0)
|
||||||
|
+ else if (strcasecmp("UARTType", child->key) == 0) {
|
||||||
|
+#if defined(linux) && !LEGACY_LIBMODBUS && LIBMODBUS_VERSION_CHECK(2, 9, 4)
|
||||||
|
+ char buffer[NI_MAXHOST];
|
||||||
|
+ status = cf_util_get_string_buffer(child, buffer, sizeof(buffer));
|
||||||
|
+ if (status != 0)
|
||||||
|
+ break;
|
||||||
|
+ if (strncmp(buffer, "RS485", 6) == 0)
|
||||||
|
+ host->uarttype = UARTTYPE_RS485;
|
||||||
|
+ else if (strncmp(buffer, "RS422", 6) == 0)
|
||||||
|
+ host->uarttype = UARTTYPE_RS422;
|
||||||
|
+ else if (strncmp(buffer, "RS232", 6) == 0)
|
||||||
|
+ host->uarttype = UARTTYPE_RS232;
|
||||||
|
+ else {
|
||||||
|
+ ERROR("Modbus plugin: The UARTType \"%s\" is unknown.", buffer);
|
||||||
|
+ status = -1;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+#else
|
||||||
|
+ ERROR("Modbus plugin: Option `UARTType' not supported. Please "
|
||||||
|
+ "upgrade libmodbus to at least 2.9.4");
|
||||||
|
+ return -1;
|
||||||
|
+#endif
|
||||||
|
+ } else if (strcasecmp("Interval", child->key) == 0)
|
||||||
|
status = cf_util_get_cdtime(child, &host->interval);
|
||||||
|
else if (strcasecmp("Slave", child->key) == 0)
|
||||||
|
/* Don't set status: Gracefully continue if a slave fails. */
|
Loading…
Reference in a new issue