You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

179 lines
7.1 KiB

  1. From 6028f89df95b12219d735b277863f83e9f5ee9e9 Mon Sep 17 00:00:00 2001
  2. From: PJ Bostley <pbostley@gmail.com>
  3. Date: Sat, 20 Jan 2018 16:39:36 -0700
  4. Subject: [PATCH 1/2] Adding support for CDAB endian 32-bit modbus polls
  5. ---
  6. src/modbus.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
  7. 1 file changed, 56 insertions(+), 5 deletions(-)
  8. diff --git a/src/modbus.c b/src/modbus.c
  9. index 31f0c2da81..daa3c028f5 100644
  10. --- a/src/modbus.c
  11. +++ b/src/modbus.c
  12. @@ -76,9 +76,13 @@
  13. enum mb_register_type_e /* {{{ */
  14. { REG_TYPE_INT16,
  15. REG_TYPE_INT32,
  16. + REG_TYPE_INT32_CDAB,
  17. REG_TYPE_UINT16,
  18. REG_TYPE_UINT32,
  19. - REG_TYPE_FLOAT }; /* }}} */
  20. + REG_TYPE_UINT32_CDAB,
  21. + REG_TYPE_FLOAT,
  22. + REG_TYPE_FLOAT_CDAB }; /* }}} */
  23. +
  24. enum mb_mreg_type_e /* {{{ */
  25. { MREG_HOLDING,
  26. MREG_INPUT }; /* }}} */
  27. @@ -425,7 +429,9 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */
  28. if ((ds->ds[0].type != DS_TYPE_GAUGE) &&
  29. (data->register_type != REG_TYPE_INT32) &&
  30. - (data->register_type != REG_TYPE_UINT32)) {
  31. + (data->register_type != REG_TYPE_INT32_CDAB) &&
  32. + (data->register_type != REG_TYPE_UINT32) &&
  33. + (data->register_type != REG_TYPE_UINT32_CDAB)) {
  34. NOTICE(
  35. "Modbus plugin: The data source of type \"%s\" is %s, not gauge. "
  36. "This will most likely result in problems, because the register type "
  37. @@ -434,8 +440,11 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */
  38. }
  39. if ((data->register_type == REG_TYPE_INT32) ||
  40. + (data->register_type == REG_TYPE_INT32_CDAB) ||
  41. (data->register_type == REG_TYPE_UINT32) ||
  42. - (data->register_type == REG_TYPE_FLOAT))
  43. + (data->register_type == REG_TYPE_UINT32_CDAB) ||
  44. + (data->register_type == REG_TYPE_FLOAT) ||
  45. + (data->register_type == REG_TYPE_FLOAT_CDAB))
  46. values_num = 2;
  47. else
  48. values_num = 1;
  49. @@ -496,8 +505,8 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */
  50. }
  51. if (status != values_num) {
  52. ERROR("Modbus plugin: modbus read function (%s/%s) failed. "
  53. - " status = %i, values_num = %i. Giving up.",
  54. - host->host, host->node, status, values_num);
  55. + " status = %i, start_addr = %i, values_num = %i. Giving up.",
  56. + host->host, host->node, status, data->register_base, values_num);
  57. #if LEGACY_LIBMODBUS
  58. modbus_close(&host->connection);
  59. #else
  60. @@ -521,6 +530,17 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */
  61. "Returned float value is %g",
  62. (double)float_value);
  63. + CAST_TO_VALUE_T(ds, vt, float_value);
  64. + mb_submit(host, slave, data, vt);
  65. + } else if (data->register_type == REG_TYPE_FLOAT_CDAB) {
  66. + float float_value;
  67. + value_t vt;
  68. +
  69. + float_value = mb_register_to_float(values[1], values[0]);
  70. + DEBUG("Modbus plugin: mb_read_data: "
  71. + "Returned float value is %g",
  72. + (double)float_value);
  73. +
  74. CAST_TO_VALUE_T(ds, vt, float_value);
  75. mb_submit(host, slave, data, vt);
  76. } else if (data->register_type == REG_TYPE_INT32) {
  77. @@ -535,6 +555,20 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */
  78. "Returned int32 value is %" PRIi32,
  79. v.i32);
  80. + CAST_TO_VALUE_T(ds, vt, v.i32);
  81. + mb_submit(host, slave, data, vt);
  82. + } else if (data->register_type == REG_TYPE_INT32_CDAB) {
  83. + union {
  84. + uint32_t u32;
  85. + int32_t i32;
  86. + } v;
  87. + value_t vt;
  88. +
  89. + v.u32 = (((uint32_t)values[1]) << 16) | ((uint32_t)values[0]);
  90. + DEBUG("Modbus plugin: mb_read_data: "
  91. + "Returned int32 value is %" PRIi32,
  92. + v.i32);
  93. +
  94. CAST_TO_VALUE_T(ds, vt, v.i32);
  95. mb_submit(host, slave, data, vt);
  96. } else if (data->register_type == REG_TYPE_INT16) {
  97. @@ -561,6 +595,17 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */
  98. "Returned uint32 value is %" PRIu32,
  99. v32);
  100. + CAST_TO_VALUE_T(ds, vt, v32);
  101. + mb_submit(host, slave, data, vt);
  102. + } else if (data->register_type == REG_TYPE_UINT32_CDAB) {
  103. + uint32_t v32;
  104. + value_t vt;
  105. +
  106. + v32 = (((uint32_t)values[1]) << 16) | ((uint32_t)values[0]);
  107. + DEBUG("Modbus plugin: mb_read_data: "
  108. + "Returned uint32 value is %" PRIu32,
  109. + v32);
  110. +
  111. CAST_TO_VALUE_T(ds, vt, v32);
  112. mb_submit(host, slave, data, vt);
  113. } else /* if (data->register_type == REG_TYPE_UINT16) */
  114. @@ -702,12 +747,18 @@ static int mb_config_add_data(oconfig_item_t *ci) /* {{{ */
  115. data.register_type = REG_TYPE_INT16;
  116. else if (strcasecmp("Int32", tmp) == 0)
  117. data.register_type = REG_TYPE_INT32;
  118. + else if (strcasecmp("Int32LE", tmp) == 0)
  119. + data.register_type = REG_TYPE_INT32_CDAB;
  120. else if (strcasecmp("Uint16", tmp) == 0)
  121. data.register_type = REG_TYPE_UINT16;
  122. else if (strcasecmp("Uint32", tmp) == 0)
  123. data.register_type = REG_TYPE_UINT32;
  124. + else if (strcasecmp("Uint32LE", tmp) == 0)
  125. + data.register_type = REG_TYPE_UINT32_CDAB;
  126. else if (strcasecmp("Float", tmp) == 0)
  127. data.register_type = REG_TYPE_FLOAT;
  128. + else if (strcasecmp("FloatLE", tmp) == 0)
  129. + data.register_type = REG_TYPE_FLOAT_CDAB;
  130. else {
  131. ERROR("Modbus plugin: The register type \"%s\" is unknown.", tmp);
  132. status = -1;
  133. From 67afd2685892e69ababb489f48b9033ab5908f4d Mon Sep 17 00:00:00 2001
  134. From: PJ Bostley <pbostley@gmail.com>
  135. Date: Tue, 23 Jan 2018 15:33:23 -0700
  136. Subject: [PATCH 2/2] Adding documentation for the Modbus little endian modes
  137. where 32 bit values have thier registers swapped
  138. ---
  139. src/collectd.conf.pod | 18 +++++++++++++-----
  140. 1 file changed, 13 insertions(+), 5 deletions(-)
  141. diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod
  142. index dfd785a2c8..e9715126e6 100644
  143. --- a/src/collectd.conf.pod
  144. +++ b/src/collectd.conf.pod
  145. @@ -4128,11 +4128,19 @@ Configures the base register to read from the device. If the option
  146. B<RegisterType> has been set to B<Uint32> or B<Float>, this and the next
  147. register will be read (the register number is increased by one).
  148. -=item B<RegisterType> B<Int16>|B<Int32>|B<Uint16>|B<Uint32>|B<Float>
  149. -
  150. -Specifies what kind of data is returned by the device. If the type is B<Int32>,
  151. -B<Uint32> or B<Float>, two 16E<nbsp>bit registers will be read and the data is
  152. -combined into one value. Defaults to B<Uint16>.
  153. +=item B<RegisterType> B<Int16>|B<Int32>|B<Uint16>|B<Uint32>|B<Float>|B<Int32LE>|B<Uint32LE>|B<FloatLE>
  154. +
  155. +Specifies what kind of data is returned by the device. This defaults to
  156. +B<Uint16>. If the type is B<Int32>, B<Int32LE>, B<Uint32>, B<Uint32LE>,
  157. +B<Float> or B<FloatLE>, two 16E<nbsp>bit registers at B<RegisterBase>
  158. +and B<RegisterBase+1> will be read and the data is combined into one
  159. +32E<nbsp>value. For B<Int32>, B<Uint32> and B<Float> the most significant
  160. +16E<nbsp>bits are in the register at B<RegisterBase> and the least
  161. +significant 16E<nbsp>bits are in the register at B<RegisterBase+1>.
  162. +For B<Int32LE>, B<Uint32LE>, or B<Float32LE>, the high and low order
  163. +registers are swapped with the most significant 16E<nbsp>bits in
  164. +the B<RegisterBase+1> and the least significant 16E<nbsp>bits in
  165. +B<RegisterBase>.
  166. =item B<RegisterCmd> B<ReadHolding>|B<ReadInput>