From 59ec4cc5d70f628276bf163f6d99e48c786221b8 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Wed, 21 Feb 2018 16:49:03 +0100 Subject: [PATCH] collectd: modbus: backport support for little-endian values Support for little-endian word-order of 32-bit fields was added upstream recently. Import the corresponding PR https://github.com/collectd/collectd/pull/2660 into a local patch and bump package release. Signed-off-by: Daniel Golle --- utils/collectd/Makefile | 2 +- .../050-backport-modbus-little-endian.patch | 179 ++++++++++++++++++ 2 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 utils/collectd/patches/050-backport-modbus-little-endian.patch diff --git a/utils/collectd/Makefile b/utils/collectd/Makefile index aa76033ee..ed22103f6 100644 --- a/utils/collectd/Makefile +++ b/utils/collectd/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=collectd PKG_VERSION:=5.8.0 -PKG_RELEASE:=3 +PKG_RELEASE:=4 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 PKG_SOURCE_URL:=https://collectd.org/files/ \ diff --git a/utils/collectd/patches/050-backport-modbus-little-endian.patch b/utils/collectd/patches/050-backport-modbus-little-endian.patch new file mode 100644 index 000000000..6cb970393 --- /dev/null +++ b/utils/collectd/patches/050-backport-modbus-little-endian.patch @@ -0,0 +1,179 @@ +From 6028f89df95b12219d735b277863f83e9f5ee9e9 Mon Sep 17 00:00:00 2001 +From: PJ Bostley +Date: Sat, 20 Jan 2018 16:39:36 -0700 +Subject: [PATCH 1/2] Adding support for CDAB endian 32-bit modbus polls + +--- + src/modbus.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 56 insertions(+), 5 deletions(-) + +diff --git a/src/modbus.c b/src/modbus.c +index 31f0c2da81..daa3c028f5 100644 +--- a/src/modbus.c ++++ b/src/modbus.c +@@ -76,9 +76,13 @@ + enum mb_register_type_e /* {{{ */ + { REG_TYPE_INT16, + REG_TYPE_INT32, ++ REG_TYPE_INT32_CDAB, + REG_TYPE_UINT16, + REG_TYPE_UINT32, +- REG_TYPE_FLOAT }; /* }}} */ ++ REG_TYPE_UINT32_CDAB, ++ REG_TYPE_FLOAT, ++ REG_TYPE_FLOAT_CDAB }; /* }}} */ ++ + enum mb_mreg_type_e /* {{{ */ + { MREG_HOLDING, + MREG_INPUT }; /* }}} */ +@@ -425,7 +429,9 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */ + + if ((ds->ds[0].type != DS_TYPE_GAUGE) && + (data->register_type != REG_TYPE_INT32) && +- (data->register_type != REG_TYPE_UINT32)) { ++ (data->register_type != REG_TYPE_INT32_CDAB) && ++ (data->register_type != REG_TYPE_UINT32) && ++ (data->register_type != REG_TYPE_UINT32_CDAB)) { + NOTICE( + "Modbus plugin: The data source of type \"%s\" is %s, not gauge. " + "This will most likely result in problems, because the register type " +@@ -434,8 +440,11 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */ + } + + if ((data->register_type == REG_TYPE_INT32) || ++ (data->register_type == REG_TYPE_INT32_CDAB) || + (data->register_type == REG_TYPE_UINT32) || +- (data->register_type == REG_TYPE_FLOAT)) ++ (data->register_type == REG_TYPE_UINT32_CDAB) || ++ (data->register_type == REG_TYPE_FLOAT) || ++ (data->register_type == REG_TYPE_FLOAT_CDAB)) + values_num = 2; + else + values_num = 1; +@@ -496,8 +505,8 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */ + } + if (status != values_num) { + ERROR("Modbus plugin: modbus read function (%s/%s) failed. " +- " status = %i, values_num = %i. Giving up.", +- host->host, host->node, status, values_num); ++ " status = %i, start_addr = %i, values_num = %i. Giving up.", ++ host->host, host->node, status, data->register_base, values_num); + #if LEGACY_LIBMODBUS + modbus_close(&host->connection); + #else +@@ -521,6 +530,17 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */ + "Returned float value is %g", + (double)float_value); + ++ CAST_TO_VALUE_T(ds, vt, float_value); ++ mb_submit(host, slave, data, vt); ++ } else if (data->register_type == REG_TYPE_FLOAT_CDAB) { ++ float float_value; ++ value_t vt; ++ ++ float_value = mb_register_to_float(values[1], values[0]); ++ DEBUG("Modbus plugin: mb_read_data: " ++ "Returned float value is %g", ++ (double)float_value); ++ + CAST_TO_VALUE_T(ds, vt, float_value); + mb_submit(host, slave, data, vt); + } else if (data->register_type == REG_TYPE_INT32) { +@@ -535,6 +555,20 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */ + "Returned int32 value is %" PRIi32, + v.i32); + ++ CAST_TO_VALUE_T(ds, vt, v.i32); ++ mb_submit(host, slave, data, vt); ++ } else if (data->register_type == REG_TYPE_INT32_CDAB) { ++ union { ++ uint32_t u32; ++ int32_t i32; ++ } v; ++ value_t vt; ++ ++ v.u32 = (((uint32_t)values[1]) << 16) | ((uint32_t)values[0]); ++ DEBUG("Modbus plugin: mb_read_data: " ++ "Returned int32 value is %" PRIi32, ++ v.i32); ++ + CAST_TO_VALUE_T(ds, vt, v.i32); + mb_submit(host, slave, data, vt); + } else if (data->register_type == REG_TYPE_INT16) { +@@ -561,6 +595,17 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */ + "Returned uint32 value is %" PRIu32, + v32); + ++ CAST_TO_VALUE_T(ds, vt, v32); ++ mb_submit(host, slave, data, vt); ++ } else if (data->register_type == REG_TYPE_UINT32_CDAB) { ++ uint32_t v32; ++ value_t vt; ++ ++ v32 = (((uint32_t)values[1]) << 16) | ((uint32_t)values[0]); ++ DEBUG("Modbus plugin: mb_read_data: " ++ "Returned uint32 value is %" PRIu32, ++ v32); ++ + CAST_TO_VALUE_T(ds, vt, v32); + mb_submit(host, slave, data, vt); + } else /* if (data->register_type == REG_TYPE_UINT16) */ +@@ -702,12 +747,18 @@ static int mb_config_add_data(oconfig_item_t *ci) /* {{{ */ + data.register_type = REG_TYPE_INT16; + else if (strcasecmp("Int32", tmp) == 0) + data.register_type = REG_TYPE_INT32; ++ else if (strcasecmp("Int32LE", tmp) == 0) ++ data.register_type = REG_TYPE_INT32_CDAB; + else if (strcasecmp("Uint16", tmp) == 0) + data.register_type = REG_TYPE_UINT16; + else if (strcasecmp("Uint32", tmp) == 0) + data.register_type = REG_TYPE_UINT32; ++ else if (strcasecmp("Uint32LE", tmp) == 0) ++ data.register_type = REG_TYPE_UINT32_CDAB; + else if (strcasecmp("Float", tmp) == 0) + data.register_type = REG_TYPE_FLOAT; ++ else if (strcasecmp("FloatLE", tmp) == 0) ++ data.register_type = REG_TYPE_FLOAT_CDAB; + else { + ERROR("Modbus plugin: The register type \"%s\" is unknown.", tmp); + status = -1; + +From 67afd2685892e69ababb489f48b9033ab5908f4d Mon Sep 17 00:00:00 2001 +From: PJ Bostley +Date: Tue, 23 Jan 2018 15:33:23 -0700 +Subject: [PATCH 2/2] Adding documentation for the Modbus little endian modes + where 32 bit values have thier registers swapped + +--- + src/collectd.conf.pod | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod +index dfd785a2c8..e9715126e6 100644 +--- a/src/collectd.conf.pod ++++ b/src/collectd.conf.pod +@@ -4128,11 +4128,19 @@ Configures the base register to read from the device. If the option + B has been set to B or B, this and the next + register will be read (the register number is increased by one). + +-=item B B|B|B|B|B +- +-Specifies what kind of data is returned by the device. If the type is B, +-B or B, two 16Ebit registers will be read and the data is +-combined into one value. Defaults to B. ++=item B B|B|B|B|B|B|B|B ++ ++Specifies what kind of data is returned by the device. This defaults to ++B. If the type is B, B, B, B, ++B or B, two 16Ebit registers at B ++and B will be read and the data is combined into one ++32Evalue. For B, B and B the most significant ++16Ebits are in the register at B and the least ++significant 16Ebits are in the register at B. ++For B, B, or B, the high and low order ++registers are swapped with the most significant 16Ebits in ++the B and the least significant 16Ebits in ++B. + + =item B B|B +