Merge pull request #2618 from ajssmith/amqp1_dev1_branch
[collectd.git] / src / modbus.c
index 5d29791..efcf6be 100644 (file)
 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 }; /* }}} */
@@ -131,7 +135,7 @@ struct mb_host_s /* {{{ */
 #else
   modbus_t *connection;
 #endif
-  _Bool is_connected;
+  bool is_connected;
 }; /* }}} */
 typedef struct mb_host_s mb_host_t;
 
@@ -148,7 +152,7 @@ struct mb_data_group_s /* {{{ */
 /*
  * Global variables
  */
-static mb_data_t *data_definitions = NULL;
+static mb_data_t *data_definitions;
 
 /*
  * Functions
@@ -156,13 +160,13 @@ static mb_data_t *data_definitions = NULL;
 static mb_data_t *data_get_by_name(mb_data_t *src, /* {{{ */
                                    const char *name) {
   if (name == NULL)
-    return (NULL);
+    return NULL;
 
   for (mb_data_t *ptr = src; ptr != NULL; ptr = ptr->next)
     if (strcasecmp(ptr->name, name) == 0)
-      return (ptr);
+      return ptr;
 
-  return (NULL);
+  return NULL;
 } /* }}} mb_data_t *data_get_by_name */
 
 static int data_append(mb_data_t **dst, mb_data_t *src) /* {{{ */
@@ -170,13 +174,13 @@ static int data_append(mb_data_t **dst, mb_data_t *src) /* {{{ */
   mb_data_t *ptr;
 
   if ((dst == NULL) || (src == NULL))
-    return (EINVAL);
+    return EINVAL;
 
   ptr = *dst;
 
   if (ptr == NULL) {
     *dst = src;
-    return (0);
+    return 0;
   }
 
   while (ptr->next != NULL)
@@ -184,7 +188,7 @@ static int data_append(mb_data_t **dst, mb_data_t *src) /* {{{ */
 
   ptr->next = src;
 
-  return (0);
+  return 0;
 } /* }}} int data_append */
 
 /* Copy a single mb_data_t and append it to another list. */
@@ -194,11 +198,11 @@ static int data_copy(mb_data_t **dst, const mb_data_t *src) /* {{{ */
   int status;
 
   if ((dst == NULL) || (src == NULL))
-    return (EINVAL);
+    return EINVAL;
 
   tmp = malloc(sizeof(*tmp));
   if (tmp == NULL)
-    return (ENOMEM);
+    return ENOMEM;
   memcpy(tmp, src, sizeof(*tmp));
   tmp->name = NULL;
   tmp->next = NULL;
@@ -206,17 +210,17 @@ static int data_copy(mb_data_t **dst, const mb_data_t *src) /* {{{ */
   tmp->name = strdup(src->name);
   if (tmp->name == NULL) {
     sfree(tmp);
-    return (ENOMEM);
+    return ENOMEM;
   }
 
   status = data_append(dst, tmp);
   if (status != 0) {
     sfree(tmp->name);
     sfree(tmp);
-    return (status);
+    return status;
   }
 
-  return (0);
+  return 0;
 } /* }}} int data_copy */
 
 /* Lookup a single mb_data_t instance, copy it and append the copy to another
@@ -226,13 +230,13 @@ static int data_copy_by_name(mb_data_t **dst, mb_data_t *src, /* {{{ */
   mb_data_t *ptr;
 
   if ((dst == NULL) || (src == NULL) || (name == NULL))
-    return (EINVAL);
+    return EINVAL;
 
   ptr = data_get_by_name(src, name);
   if (ptr == NULL)
-    return (ENOENT);
+    return ENOENT;
 
-  return (data_copy(dst, ptr));
+  return data_copy(dst, ptr);
 } /* }}} int data_copy_by_name */
 
 /* Read functions */
@@ -242,13 +246,13 @@ static int mb_submit(mb_host_t *host, mb_slave_t *slave, /* {{{ */
   value_list_t vl = VALUE_LIST_INIT;
 
   if ((host == NULL) || (slave == NULL) || (data == NULL))
-    return (EINVAL);
+    return EINVAL;
 
   if (host->interval == 0)
     host->interval = plugin_get_interval();
 
   if (slave->instance[0] == 0)
-    ssnprintf(slave->instance, sizeof(slave->instance), "slave_%i", slave->id);
+    snprintf(slave->instance, sizeof(slave->instance), "slave_%i", slave->id);
 
   vl.values = &value;
   vl.values_len = 1;
@@ -259,7 +263,7 @@ static int mb_submit(mb_host_t *host, mb_slave_t *slave, /* {{{ */
   sstrncpy(vl.type, data->type, sizeof(vl.type));
   sstrncpy(vl.type_instance, data->instance, sizeof(vl.type_instance));
 
-  return (plugin_dispatch_values(&vl));
+  return plugin_dispatch_values(&vl);
 } /* }}} int mb_submit */
 
 static float mb_register_to_float(uint16_t hi, uint16_t lo) /* {{{ */
@@ -283,7 +287,7 @@ static float mb_register_to_float(uint16_t hi, uint16_t lo) /* {{{ */
   conv.b[0] = (hi >> 8) & 0x00ff;
 #endif
 
-  return (conv.f);
+  return conv.f;
 } /* }}} float mb_register_to_float */
 
 #if LEGACY_LIBMODBUS
@@ -293,7 +297,7 @@ static int mb_init_connection(mb_host_t *host) /* {{{ */
   int status;
 
   if (host == NULL)
-    return (EINVAL);
+    return EINVAL;
 
 #if COLLECT_DEBUG
   modbus_set_debug(&host->connection, 1);
@@ -325,11 +329,11 @@ static int mb_init_connection(mb_host_t *host) /* {{{ */
   if (status != 0) {
     ERROR("Modbus plugin: modbus_connect (%s, %i) failed with status %i.",
           host->node, host->port ? host->port : host->baudrate, status);
-    return (status);
+    return status;
   }
 
-  host->is_connected = 1;
-  return (0);
+  host->is_connected = true;
+  return 0;
 } /* }}} int mb_init_connection */
 /* #endif LEGACY_LIBMODBUS */
 
@@ -340,10 +344,10 @@ static int mb_init_connection(mb_host_t *host) /* {{{ */
   int status;
 
   if (host == NULL)
-    return (EINVAL);
+    return EINVAL;
 
   if (host->connection != NULL)
-    return (0);
+    return 0;
 
   if (host->conntype == MBCONN_TCP) {
     if ((host->port < 1) || (host->port > 65535))
@@ -355,7 +359,7 @@ static int mb_init_connection(mb_host_t *host) /* {{{ */
     host->connection = modbus_new_tcp(host->node, host->port);
     if (host->connection == NULL) {
       ERROR("Modbus plugin: Creating new Modbus/TCP object failed.");
-      return (-1);
+      return -1;
     }
   } else {
     DEBUG("Modbus plugin: Trying to connect to \"%s\", baudrate %i.",
@@ -364,7 +368,7 @@ static int mb_init_connection(mb_host_t *host) /* {{{ */
     host->connection = modbus_new_rtu(host->node, host->baudrate, 'N', 8, 1);
     if (host->connection == NULL) {
       ERROR("Modbus plugin: Creating new Modbus/RTU object failed.");
-      return (-1);
+      return -1;
     }
   }
 
@@ -381,10 +385,10 @@ static int mb_init_connection(mb_host_t *host) /* {{{ */
           host->node, host->port ? host->port : host->baudrate, status);
     modbus_free(host->connection);
     host->connection = NULL;
-    return (status);
+    return status;
   }
 
-  return (0);
+  return 0;
 } /* }}} int mb_init_connection */
 #endif /* !LEGACY_LIBMODBUS */
 
@@ -408,24 +412,26 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */
   int status = 0;
 
   if ((host == NULL) || (slave == NULL) || (data == NULL))
-    return (EINVAL);
+    return EINVAL;
 
   ds = plugin_get_ds(data->type);
   if (ds == NULL) {
     ERROR("Modbus plugin: Type \"%s\" is not defined.", data->type);
-    return (-1);
+    return -1;
   }
 
   if (ds->ds_num != 1) {
-    ERROR("Modbus plugin: The type \"%s\" has %zu data sources. "
+    ERROR("Modbus plugin: The type \"%s\" has %" PRIsz " data sources. "
           "I can only handle data sets with only one data source.",
           data->type, ds->ds_num);
-    return (-1);
+    return -1;
   }
 
   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;
@@ -456,9 +465,9 @@ 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);
+      return -1;
     }
   } else if (status != 0) {
 #if LEGACY_LIBMODBUS
@@ -480,7 +489,7 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */
   if (status != 0) {
     ERROR("Modbus plugin: modbus_set_slave (%i) failed with status %i.",
           slave->id, status);
-    return (-1);
+    return -1;
   }
 #endif
   if (data->modbus_register_type == MREG_INPUT) {
@@ -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
@@ -505,7 +514,7 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */
     modbus_free(host->connection);
 #endif
     host->connection = NULL;
-    return (-1);
+    return -1;
   }
 
   DEBUG("Modbus plugin: mb_read_data: Success! "
@@ -523,6 +532,17 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */
 
     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) {
     union {
       uint32_t u32;
@@ -537,6 +557,20 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */
 
     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) {
     union {
       uint16_t u16;
@@ -563,6 +597,17 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */
 
     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) */
   {
     value_t vt;
@@ -575,7 +620,7 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */
     mb_submit(host, slave, data, vt);
   }
 
-  return (0);
+  return 0;
 } /* }}} int mb_read_data */
 
 static int mb_read_slave(mb_host_t *host, mb_slave_t *slave) /* {{{ */
@@ -584,7 +629,7 @@ static int mb_read_slave(mb_host_t *host, mb_slave_t *slave) /* {{{ */
   int status;
 
   if ((host == NULL) || (slave == NULL))
-    return (EINVAL);
+    return EINVAL;
 
   success = 0;
   for (mb_data_t *data = slave->collect; data != NULL; data = data->next) {
@@ -594,9 +639,9 @@ static int mb_read_slave(mb_host_t *host, mb_slave_t *slave) /* {{{ */
   }
 
   if (success == 0)
-    return (-1);
+    return -1;
   else
-    return (0);
+    return 0;
 } /* }}} int mb_read_slave */
 
 static int mb_read(user_data_t *user_data) /* {{{ */
@@ -606,7 +651,7 @@ static int mb_read(user_data_t *user_data) /* {{{ */
   int status;
 
   if ((user_data == NULL) || (user_data->data == NULL))
-    return (EINVAL);
+    return EINVAL;
 
   host = user_data->data;
 
@@ -618,9 +663,9 @@ static int mb_read(user_data_t *user_data) /* {{{ */
   }
 
   if (success == 0)
-    return (-1);
+    return -1;
   else
-    return (0);
+    return 0;
 } /* }}} int mb_read */
 
 /* Free functions */
@@ -681,7 +726,7 @@ static int mb_config_add_data(oconfig_item_t *ci) /* {{{ */
 
   status = cf_util_get_string(ci, &data.name);
   if (status != 0)
-    return (status);
+    return status;
 
   for (int i = 0; i < ci->children_num; i++) {
     oconfig_item_t *child = ci->children + i;
@@ -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;
@@ -752,7 +803,7 @@ static int mb_config_add_data(oconfig_item_t *ci) /* {{{ */
 
   sfree(data.name);
 
-  return (status);
+  return status;
 } /* }}} int mb_config_add_data */
 
 static int mb_config_set_host_address(mb_host_t *host, /* {{{ */
@@ -761,7 +812,7 @@ static int mb_config_set_host_address(mb_host_t *host, /* {{{ */
   int status;
 
   if ((host == NULL) || (address == NULL))
-    return (EINVAL);
+    return EINVAL;
 
   struct addrinfo ai_hints = {
       /* XXX: libmodbus can only handle IPv4 addresses. */
@@ -770,11 +821,9 @@ static int mb_config_set_host_address(mb_host_t *host, /* {{{ */
 
   status = getaddrinfo(address, /* service = */ NULL, &ai_hints, &ai_list);
   if (status != 0) {
-    char errbuf[1024];
     ERROR("Modbus plugin: getaddrinfo failed: %s",
-          (status == EAI_SYSTEM) ? sstrerror(errno, errbuf, sizeof(errbuf))
-                                 : gai_strerror(status));
-    return (status);
+          (status == EAI_SYSTEM) ? STRERRNO : gai_strerror(status));
+    return status;
   }
 
   for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL;
@@ -797,7 +846,7 @@ static int mb_config_set_host_address(mb_host_t *host, /* {{{ */
           host->node);
   }
 
-  return (status);
+  return status;
 } /* }}} int mb_config_set_host_address */
 
 static int mb_config_add_slave(mb_host_t *host, oconfig_item_t *ci) /* {{{ */
@@ -806,11 +855,11 @@ static int mb_config_add_slave(mb_host_t *host, oconfig_item_t *ci) /* {{{ */
   int status;
 
   if ((host == NULL) || (ci == NULL))
-    return (EINVAL);
+    return EINVAL;
 
   slave = realloc(host->slaves, sizeof(*slave) * (host->slaves_num + 1));
   if (slave == NULL)
-    return (ENOMEM);
+    return ENOMEM;
   host->slaves = slave;
   slave = host->slaves + host->slaves_num;
   memset(slave, 0, sizeof(*slave));
@@ -818,7 +867,7 @@ static int mb_config_add_slave(mb_host_t *host, oconfig_item_t *ci) /* {{{ */
 
   status = cf_util_get_int(ci, &slave->id);
   if (status != 0)
-    return (status);
+    return status;
 
   for (int i = 0; i < ci->children_num; i++) {
     oconfig_item_t *child = ci->children + i;
@@ -852,7 +901,7 @@ static int mb_config_add_slave(mb_host_t *host, oconfig_item_t *ci) /* {{{ */
   else /* if (status != 0) */
     data_free_all(slave->collect);
 
-  return (status);
+  return status;
 } /* }}} int mb_config_add_slave */
 
 static int mb_config_add_host(oconfig_item_t *ci) /* {{{ */
@@ -862,17 +911,17 @@ static int mb_config_add_host(oconfig_item_t *ci) /* {{{ */
 
   host = calloc(1, sizeof(*host));
   if (host == NULL)
-    return (ENOMEM);
+    return ENOMEM;
   host->slaves = NULL;
 
   status = cf_util_get_string_buffer(ci, host->host, sizeof(host->host));
   if (status != 0) {
     sfree(host);
-    return (status);
+    return status;
   }
   if (host->host[0] == 0) {
     sfree(host);
-    return (EINVAL);
+    return EINVAL;
   }
 
   for (int i = 0; i < ci->children_num; i++) {
@@ -934,7 +983,7 @@ static int mb_config_add_host(oconfig_item_t *ci) /* {{{ */
   if (status == 0) {
     char name[1024];
 
-    ssnprintf(name, sizeof(name), "modbus-%s", host->host);
+    snprintf(name, sizeof(name), "modbus-%s", host->host);
 
     plugin_register_complex_read(/* group = */ NULL, name,
                                  /* callback = */ mb_read,
@@ -946,13 +995,13 @@ static int mb_config_add_host(oconfig_item_t *ci) /* {{{ */
     host_free(host);
   }
 
-  return (status);
+  return status;
 } /* }}} int mb_config_add_host */
 
 static int mb_config(oconfig_item_t *ci) /* {{{ */
 {
   if (ci == NULL)
-    return (EINVAL);
+    return EINVAL;
 
   for (int i = 0; i < ci->children_num; i++) {
     oconfig_item_t *child = ci->children + i;
@@ -965,7 +1014,7 @@ static int mb_config(oconfig_item_t *ci) /* {{{ */
       ERROR("Modbus plugin: Unknown configuration option: %s", child->key);
   }
 
-  return (0);
+  return 0;
 } /* }}} int mb_config */
 
 /* ========= */
@@ -975,12 +1024,10 @@ static int mb_shutdown(void) /* {{{ */
   data_free_all(data_definitions);
   data_definitions = NULL;
 
-  return (0);
+  return 0;
 } /* }}} int mb_shutdown */
 
 void module_register(void) {
   plugin_register_complex_config("modbus", mb_config);
   plugin_register_shutdown("modbus", mb_shutdown);
 } /* void module_register */
-
-/* vim: set sw=2 sts=2 et fdm=marker : */