Merge branch 'collectd-5.8'
[collectd.git] / src / modbus.c
index 6422774..0a4f40c 100644 (file)
@@ -80,6 +80,8 @@ enum mb_register_type_e /* {{{ */
   REG_TYPE_UINT16,
   REG_TYPE_UINT32,
   REG_TYPE_UINT32_CDAB,
+  REG_TYPE_INT64,
+  REG_TYPE_UINT64,
   REG_TYPE_FLOAT,
   REG_TYPE_FLOAT_CDAB }; /* }}} */
 
@@ -127,7 +129,6 @@ struct mb_host_s /* {{{ */
   int port;     /* for Modbus/TCP */
   int baudrate; /* for Modbus/RTU */
   mb_conntype_t conntype;
-  cdtime_t interval;
 
   mb_slave_t *slaves;
   size_t slaves_num;
@@ -137,7 +138,7 @@ struct mb_host_s /* {{{ */
 #else
   modbus_t *connection;
 #endif
-  _Bool is_connected;
+  bool is_connected;
 }; /* }}} */
 typedef struct mb_host_s mb_host_t;
 
@@ -154,7 +155,7 @@ struct mb_data_group_s /* {{{ */
 /*
  * Global variables
  */
-static mb_data_t *data_definitions = NULL;
+static mb_data_t *data_definitions;
 
 /*
  * Functions
@@ -250,15 +251,11 @@ static int mb_submit(mb_host_t *host, mb_slave_t *slave, /* {{{ */
   if ((host == NULL) || (slave == NULL) || (data == NULL))
     return EINVAL;
 
-  if (host->interval == 0)
-    host->interval = plugin_get_interval();
-
   if (slave->instance[0] == 0)
     snprintf(slave->instance, sizeof(slave->instance), "slave_%i", slave->id);
 
   vl.values = &value;
   vl.values_len = 1;
-  vl.interval = host->interval;
   sstrncpy(vl.host, host->host, sizeof(vl.host));
   sstrncpy(vl.plugin, "modbus", sizeof(vl.plugin));
   sstrncpy(vl.plugin_instance, slave->instance, sizeof(vl.plugin_instance));
@@ -334,7 +331,7 @@ static int mb_init_connection(mb_host_t *host) /* {{{ */
     return status;
   }
 
-  host->is_connected = 1;
+  host->is_connected = true;
   return 0;
 } /* }}} int mb_init_connection */
 /* #endif LEGACY_LIBMODBUS */
@@ -408,7 +405,7 @@ static int mb_init_connection(mb_host_t *host) /* {{{ */
 
 static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */
                         mb_data_t *data) {
-  uint16_t values[2] = {0};
+  uint16_t values[4] = {0};
   int values_num;
   const data_set_t *ds;
   int status = 0;
@@ -433,11 +430,13 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */
       (data->register_type != REG_TYPE_INT32) &&
       (data->register_type != REG_TYPE_INT32_CDAB) &&
       (data->register_type != REG_TYPE_UINT32) &&
-      (data->register_type != REG_TYPE_UINT32_CDAB)) {
+      (data->register_type != REG_TYPE_UINT32_CDAB) &&
+      (data->register_type != REG_TYPE_INT64) &&
+      (data->register_type != REG_TYPE_UINT64)) {
     NOTICE(
         "Modbus plugin: The data source of type \"%s\" is %s, not gauge. "
         "This will most likely result in problems, because the register type "
-        "is not UINT32.",
+        "is not UINT32 or UINT64.",
         data->type, DS_TYPE_TO_STRING(ds->ds[0].type));
   }
 
@@ -448,6 +447,9 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */
       (data->register_type == REG_TYPE_FLOAT) ||
       (data->register_type == REG_TYPE_FLOAT_CDAB))
     values_num = 2;
+  else if ((data->register_type == REG_TYPE_INT64) ||
+           (data->register_type == REG_TYPE_UINT64))
+    values_num = 4;
   else
     values_num = 1;
 
@@ -467,7 +469,7 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */
     if (status != 0) {
       ERROR("Modbus plugin: mb_init_connection (%s/%s) failed. ", host->host,
             host->node);
-      host->is_connected = 0;
+      host->is_connected = false;
       host->connection = NULL;
       return -1;
     }
@@ -610,6 +612,33 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */
 
     CAST_TO_VALUE_T(ds, vt, v32, data->scale, data->shift);
     mb_submit(host, slave, data, vt);
+  } else if (data->register_type == REG_TYPE_UINT64) {
+    uint64_t v64;
+    value_t vt;
+
+    v64 = (((uint64_t)values[0]) << 48) | (((uint64_t)values[1]) << 32) |
+          (((uint64_t)values[2]) << 16) | (((uint64_t)values[3]));
+    DEBUG("Modbus plugin: mb_read_data: "
+          "Returned uint64 value is %" PRIu64,
+          v64);
+
+    CAST_TO_VALUE_T(ds, vt, v64, data->scale, data->shift);
+    mb_submit(host, slave, data, vt);
+  } else if (data->register_type == REG_TYPE_INT64) {
+    union {
+      uint64_t u64;
+      int64_t i64;
+    } v;
+    value_t vt;
+
+    v.u64 = (((uint64_t)values[0]) << 48) | (((uint64_t)values[1]) << 32) |
+            (((uint64_t)values[2]) << 16) | ((uint64_t)values[3]);
+    DEBUG("Modbus plugin: mb_read_data: "
+          "Returned uint64 value is %" PRIi64,
+          v.i64);
+
+    CAST_TO_VALUE_T(ds, vt, v.i64, data->scale, data->shift);
+    mb_submit(host, slave, data, vt);
   } else /* if (data->register_type == REG_TYPE_UINT16) */
   {
     value_t vt;
@@ -767,6 +796,10 @@ static int mb_config_add_data(oconfig_item_t *ci) /* {{{ */
         data.register_type = REG_TYPE_FLOAT;
       else if (strcasecmp("FloatLE", tmp) == 0)
         data.register_type = REG_TYPE_FLOAT_CDAB;
+      else if (strcasecmp("Uint64", tmp) == 0)
+        data.register_type = REG_TYPE_UINT64;
+      else if (strcasecmp("Int64", tmp) == 0)
+        data.register_type = REG_TYPE_INT64;
       else {
         ERROR("Modbus plugin: The register type \"%s\" is unknown.", tmp);
         status = -1;
@@ -914,6 +947,7 @@ static int mb_config_add_slave(mb_host_t *host, oconfig_item_t *ci) /* {{{ */
 
 static int mb_config_add_host(oconfig_item_t *ci) /* {{{ */
 {
+  cdtime_t interval = 0;
   mb_host_t *host;
   int status;
 
@@ -954,7 +988,7 @@ static int mb_config_add_host(oconfig_item_t *ci) /* {{{ */
     } else if (strcasecmp("Baudrate", child->key) == 0)
       status = cf_util_get_int(child, &host->baudrate);
     else if (strcasecmp("Interval", child->key) == 0)
-      status = cf_util_get_cdtime(child, &host->interval);
+      status = cf_util_get_cdtime(child, &interval);
     else if (strcasecmp("Slave", child->key) == 0)
       /* Don't set status: Gracefully continue if a slave fails. */
       mb_config_add_slave(host, child);
@@ -995,7 +1029,7 @@ static int mb_config_add_host(oconfig_item_t *ci) /* {{{ */
 
     plugin_register_complex_read(/* group = */ NULL, name,
                                  /* callback = */ mb_read,
-                                 /* interval = */ host->interval,
+                                 /* interval = */ interval,
                                  &(user_data_t){
                                      .data = host, .free_func = host_free,
                                  });