collectd: modbus: backport support for little-endian values 5650/head
authorDaniel Golle <daniel@makrotopia.org>
Wed, 21 Feb 2018 15:49:03 +0000 (16:49 +0100)
committerDaniel Golle <daniel@makrotopia.org>
Wed, 28 Feb 2018 11:51:28 +0000 (12:51 +0100)
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 <daniel@makrotopia.org>
utils/collectd/Makefile
utils/collectd/patches/050-backport-modbus-little-endian.patch [new file with mode: 0644]

index aa76033ee32f71c2f831d7b6c95be53fecb55b4f..ed22103f6f4324bf7cea714db982e9b101361006 100644 (file)
@@ -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 (file)
index 0000000..6cb9703
--- /dev/null
@@ -0,0 +1,179 @@
+From 6028f89df95b12219d735b277863f83e9f5ee9e9 Mon Sep 17 00:00:00 2001
+From: PJ Bostley <pbostley@gmail.com>
+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 <pbostley@gmail.com>
+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<RegisterType> has been set to B<Uint32> or B<Float>, this and the next
+ register will be read (the register number is increased by one).
+-=item B<RegisterType> B<Int16>|B<Int32>|B<Uint16>|B<Uint32>|B<Float>
+-
+-Specifies what kind of data is returned by the device. If the type is B<Int32>,
+-B<Uint32> or B<Float>, two 16E<nbsp>bit registers will be read and the data is
+-combined into one value. Defaults to B<Uint16>.
++=item B<RegisterType> B<Int16>|B<Int32>|B<Uint16>|B<Uint32>|B<Float>|B<Int32LE>|B<Uint32LE>|B<FloatLE>
++
++Specifies what kind of data is returned by the device. This defaults to
++B<Uint16>.  If the type is B<Int32>, B<Int32LE>, B<Uint32>, B<Uint32LE>,
++B<Float> or B<FloatLE>, two 16E<nbsp>bit registers at B<RegisterBase>
++and B<RegisterBase+1> will be read and the data is combined into one
++32E<nbsp>value. For B<Int32>, B<Uint32> and B<Float> the most significant
++16E<nbsp>bits are in the register at B<RegisterBase> and the least
++significant 16E<nbsp>bits are in the register at B<RegisterBase+1>.
++For B<Int32LE>, B<Uint32LE>, or B<Float32LE>, the high and low order
++registers are swapped with the most significant 16E<nbsp>bits in
++the B<RegisterBase+1> and the least significant 16E<nbsp>bits in
++B<RegisterBase>.
+ =item B<RegisterCmd> B<ReadHolding>|B<ReadInput>