]> git.ipfire.org Git - thirdparty/collectd.git/commitdiff
modbus: add support for double values (#4009)
authorSimon Peeters <peeters.simon@gmail.com>
Wed, 8 Jun 2022 09:53:25 +0000 (11:53 +0200)
committerGitHub <noreply@github.com>
Wed, 8 Jun 2022 09:53:25 +0000 (11:53 +0200)
src/collectd.conf.pod
src/modbus.c

index cde4bd7ed8ab55517e4a4278f529bed42bc02273..38519e8d200bb5e70bbdf111ce2e023e201988bc 100644 (file)
@@ -5179,7 +5179,7 @@ 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<Int64>|B<Uint16>|B<Uint32>|B<UInt64>|B<Float>|B<Int32LE>|B<Uint32LE>|B<FloatLE>
+=item B<RegisterType> B<Int16>|B<Int32>|B<Int64>|B<Uint16>|B<Uint32>|B<UInt64>|B<Float>|B<Int32LE>|B<Uint32LE>|B<FloatLE>|B<Double>
 
 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>,
@@ -5191,10 +5191,10 @@ 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>. If the type is B<Int64> or B<UInt64>, four 16E<nbsp>bit
-registers at B<RegisterBase>, B<RegisterBase+1>, B<RegisterBase+2> and
-B<RegisterBase+3> will be read and the data combined into one
-64E<nbsp>value.
+B<RegisterBase>. If the type is B<Int64>, B<UInt64> or B<Double>, four
+16E<nbsp>bit registers at B<RegisterBase>, B<RegisterBase+1>, B<RegisterBase+2>
+and B<RegisterBase+3> will be read and the data combined into one 64E<nbsp>bit
+value.
 
 =item B<RegisterCmd> B<ReadHolding>|B<ReadInput>
 
index e36f3daea5e0319b4190026165928f773c4c9dfa..068f73cea1cecaaa256c764d69b443bbff8a9397 100644 (file)
@@ -83,7 +83,9 @@ enum mb_register_type_e /* {{{ */
   REG_TYPE_INT64,
   REG_TYPE_UINT64,
   REG_TYPE_FLOAT,
-  REG_TYPE_FLOAT_CDAB }; /* }}} */
+  REG_TYPE_FLOAT_CDAB,
+  REG_TYPE_DOUBLE,
+}; /* }}} */
 
 enum mb_mreg_type_e /* {{{ */
 { MREG_HOLDING,
@@ -296,6 +298,38 @@ static float mb_register_to_float(uint16_t hi, uint16_t lo) /* {{{ */
   return conv.f;
 } /* }}} float mb_register_to_float */
 
+static double mb_register_to_double(uint16_t b0, uint16_t b1, uint16_t b2,
+                                    uint16_t b3) /* {{{ */
+{
+  union {
+    uint8_t b[8];
+    double d;
+  } conv;
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+  /* little endian */
+  conv.b[0] = b3 & 0x00ff;
+  conv.b[1] = (b3 >> 8) & 0x00ff;
+  conv.b[2] = b2 & 0x00ff;
+  conv.b[3] = (b2 >> 8) & 0x00ff;
+  conv.b[4] = b1 & 0x00ff;
+  conv.b[5] = (b1 >> 8) & 0x00ff;
+  conv.b[6] = b0 & 0x00ff;
+  conv.b[7] = (b0 >> 8) & 0x00ff;
+#else
+  conv.b[7] = b3 & 0x00ff;
+  conv.b[6] = (b3 >> 8) & 0x00ff;
+  conv.b[5] = b2 & 0x00ff;
+  conv.b[4] = (b2 >> 8) & 0x00ff;
+  conv.b[3] = b1 & 0x00ff;
+  conv.b[2] = (b1 >> 8) & 0x00ff;
+  conv.b[1] = b0 & 0x00ff;
+  conv.b[0] = (b0 >> 8) & 0x00ff;
+#endif
+
+  return (conv.d);
+} /* }}} double mb_register_to_double */
+
 #if LEGACY_LIBMODBUS
 /* Version 2.0.3 */
 static int mb_init_connection(mb_host_t *host) /* {{{ */
@@ -341,7 +375,7 @@ static int mb_init_connection(mb_host_t *host) /* {{{ */
   host->is_connected = true;
   return 0;
 } /* }}} int mb_init_connection */
-  /* #endif LEGACY_LIBMODBUS */
+/* #endif LEGACY_LIBMODBUS */
 
 #else /* if !LEGACY_LIBMODBUS */
 /* Version 2.9.2 */
@@ -471,7 +505,8 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */
       (data->register_type == REG_TYPE_FLOAT_CDAB))
     values_num = 2;
   else if ((data->register_type == REG_TYPE_INT64) ||
-           (data->register_type == REG_TYPE_UINT64))
+           (data->register_type == REG_TYPE_UINT64) ||
+           (data->register_type == REG_TYPE_DOUBLE))
     values_num = 4;
   else
     values_num = 1;
@@ -570,6 +605,18 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */
 
     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_DOUBLE) {
+    double double_value;
+    value_t vt;
+
+    double_value =
+        mb_register_to_double(values[0], values[1], values[2], values[3]);
+    DEBUG("Modbus plugin: mb_read_data: "
+          "Returned double value is %g",
+          double_value);
+
+    CAST_TO_VALUE_T(ds, vt, double_value, data->scale, data->shift);
+    mb_submit(host, slave, data, vt);
   } else if (data->register_type == REG_TYPE_INT32) {
     union {
       uint32_t u32;
@@ -823,6 +870,8 @@ static int mb_config_add_data(oconfig_item_t *ci) /* {{{ */
         data.register_type = REG_TYPE_UINT64;
       else if (strcasecmp("Int64", tmp) == 0)
         data.register_type = REG_TYPE_INT64;
+      else if (strcasecmp("Double", tmp) == 0)
+        data.register_type = REG_TYPE_DOUBLE;
       else {
         ERROR("Modbus plugin: The register type \"%s\" is unknown.", tmp);
         status = -1;