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 @@ -4139,11 +4139,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