Merge pull request #2670 from antvick/feature/modbus_64bit
authorPavel Rochnyak <pavel2000@ngs.ru>
Thu, 24 May 2018 14:13:10 +0000 (21:13 +0700)
committerGitHub <noreply@github.com>
Thu, 24 May 2018 14:13:10 +0000 (21:13 +0700)
modbus: Add support for 64 bit vals and update docs

1  2 
src/collectd.conf.pod
src/modbus.c

diff --combined src/collectd.conf.pod
@@@ -530,9 -530,9 +530,9 @@@ are disabled by default
  =head2 Plugin C<amqp>
  
  The I<AMQP plugin> can be used to communicate with other instances of
 -I<collectd> or third party applications using an AMQP message broker. Values
 -are sent to or received from the broker, which handles routing, queueing and
 -possibly filtering out messages.
 +I<collectd> or third party applications using an AMQP 0.9.1 message broker.
 +Values are sent to or received from the broker, which handles routing,
 +queueing and possibly filtering out messages.
  
  B<Synopsis:>
  
@@@ -738,171 -738,6 +738,171 @@@ is preserved, i.e. passed through
  
  =back
  
 +=head2 Plugin C<amqp1>
 +
 +The I<AMQP1 plugin> can be used to communicate with other instances of
 +I<collectd> or third party applications using an AMQP 1.0 message
 +intermediary. Metric values or notifications are sent to the
 +messaging intermediary which may handle direct messaging or
 +queue based transfer.
 +
 +B<Synopsis:>
 +
 + <Plugin "amqp1">
 +   # Send values to an AMQP 1.0 intermediary
 +  <Transport "name">
 +    Host "localhost"
 +    Port "5672"
 +    User "guest"
 +    Password "guest"
 +    Address "collectd"
 +#    RetryDelay 1
 +    <Instance "some_name">
 +        Format "command"
 +        PreSettle false
 +        Notify false
 + #      StoreRates false
 + #      GraphitePrefix "collectd."
 + #      GraphiteEscapeChar "_"
 + #      GraphiteSeparateInstances false
 + #      GraphiteAlwaysAppendDS false
 + #      GraphitePreserveSeparator false
 +    </Instance>
 +  </Transport>
 + </Plugin>
 +
 +The plugin's configuration consists of a I<Transport> that configures
 +communications to the AMQP 1.0 messaging bus and one or more I<Instance>
 +corresponding to metric or event publishers to the messaging system.
 +
 +The address in the I<Transport> block concatenated with the name given in the
 +I<Instance> block starting tag will be used as the send-to address for
 +communications over the messaging link.
 +
 +The following options are accepted within each I<Transport> block:
 +
 +=over 4
 +
 +=item B<Host> I<Host>
 +
 +Hostname or IP-address of the AMQP 1.0 intermediary. Defaults to the
 +default behavior of the underlying communications library,
 +I<libqpid-proton>, which is "localhost".
 +
 +=item B<Port> I<Port>
 +
 +Service name or port number on which the AMQP 1.0 intermediary accepts
 +connections. This argument must be a string, even if the numeric form
 +is used. Defaults to "5672".
 +
 +=item B<User> I<User>
 +
 +=item B<Password> I<Password>
 +
 +Credentials used to authenticate to the AMQP 1.0 intermediary. By
 +default "guest"/"guest" is used.
 +
 +=item B<Address> I<Address>
 +
 +This option specifies the prefix for the send-to value in the message.
 +By default, "collectd" will be used.
 +
 +=item B<RetryDelay> I<RetryDelay>
 +
 +When the AMQP1 connection is lost, defines the time in seconds to wait
 +before attempting to reconnect. Defaults to 1, which implies attempt
 +to reconnect at 1 second intervals.
 +
 +=back
 +
 +The following options are accepted within each I<Instance> block:
 +
 +=over 4
 +
 +=item B<Format> B<Command>|B<JSON>|B<Graphite>
 +
 +Selects the format in which messages are sent to the intermediary. If set to
 +B<Command> (the default), values are sent as C<PUTVAL> commands which are
 +identical to the syntax used by the I<Exec> and I<UnixSock plugins>. In this
 +case, the C<Content-Type> header field will be set to C<text/collectd>.
 +
 +If set to B<JSON>, the values are encoded in the I<JavaScript Object Notation>,
 +an easy and straight forward exchange format. The C<Content-Type> header field
 +will be set to C<application/json>.
 +
 +If set to B<Graphite>, values are encoded in the I<Graphite> format, which is
 +"<metric> <value> <timestamp>\n". The C<Content-Type> header field will be set to
 +C<text/graphite>.
 +
 +A subscribing client I<should> use the C<Content-Type> header field to
 +determine how to decode the values.
 +
 +=item B<PreSettle> B<true>|B<false>
 +
 +If set to B<false> (the default), the plugin will wait for a message
 +acknowledgement from the messaging bus before sending the next
 +message. This indicates transfer of ownership to the messaging
 +system. If set to B<true>, the plugin will not wait for a message
 +acknowledgement and the message may be dropped prior to transfer of
 +ownership.
 +
 +=item B<Notify> B<true>|B<false>
 +
 +If set to B<false> (the default), the plugin will service the
 +instance write call back as a value list. If set to B<true> the
 +plugin will service the instance as a write notification callback
 +for alert formatting.
 +
 +=item B<StoreRates> B<true>|B<false>
 +
 +Determines whether or not C<COUNTER>, C<DERIVE> and C<ABSOLUTE> data sources
 +are converted to a I<rate> (i.e. a C<GAUGE> value). If set to B<false> (the
 +default), no conversion is performed. Otherwise the conversion is performed
 +using the internal value cache.
 +
 +Please note that currently this option is only used if the B<Format> option has
 +been set to B<JSON>.
 +
 +=item B<GraphitePrefix>
 +
 +A prefix can be added in the metric name when outputting in the I<Graphite> format.
 +It's added before the I<Host> name.
 +Metric name will be "<prefix><host><postfix><plugin><type><name>"
 +
 +=item B<GraphitePostfix>
 +
 +A postfix can be added in the metric name when outputting in the I<Graphite> format.
 +It's added after the I<Host> name.
 +Metric name will be "<prefix><host><postfix><plugin><type><name>"
 +
 +=item B<GraphiteEscapeChar>
 +
 +Specify a character to replace dots (.) in the host part of the metric name.
 +In I<Graphite> metric name, dots are used as separators between different
 +metric parts (host, plugin, type).
 +Default is "_" (I<Underscore>).
 +
 +=item B<GraphiteSeparateInstances> B<true>|B<false>
 +
 +If set to B<true>, the plugin instance and type instance will be in their own
 +path component, for example C<host.cpu.0.cpu.idle>. If set to B<false> (the
 +default), the plugin and plugin instance (and likewise the type and type
 +instance) are put into one component, for example C<host.cpu-0.cpu-idle>.
 +
 +=item B<GraphiteAlwaysAppendDS> B<true>|B<false>
 +
 +If set to B<true>, append the name of the I<Data Source> (DS) to the "metric"
 +identifier. If set to B<false> (the default), this is only done when there is
 +more than one DS.
 +
 +=item B<GraphitePreserveSeparator> B<false>|B<true>
 +
 +If set to B<false> (the default) the C<.> (dot) character is replaced with
 +I<GraphiteEscapeChar>. Otherwise, if set to B<true>, the C<.> (dot) character
 +is preserved, i.e. passed through.
 +
 +=back
 +
  =head2 Plugin C<apache>
  
  To configure the C<apache>-plugin you first need to configure the Apache
@@@ -3347,7 -3182,6 +3347,7 @@@ B<Synopsis:
      ReportSoftwareEvents true
      EventList "/var/cache/pmu/GenuineIntel-6-2D-core.json"
      HardwareEvents "L2_RQSTS.CODE_RD_HIT,L2_RQSTS.CODE_RD_MISS" "L2_RQSTS.ALL_CODE_RD"
 +    Cores "0-3" "4,6" "[12-15]"
    </Plugin>
  
  B<Options:>
@@@ -3419,23 -3253,6 +3419,23 @@@ event_download.py script to download ev
  This field is a list of event names or groups of comma separated event names.
  This option requires B<EventList> option to be configured.
  
 +=item B<Cores> I<cores groups>
 +
 +All events are reported on a per core basis. Monitoring of the events can be
 +configured for a group of cores (aggregated statistics). This field defines
 +groups of cores on which to monitor supported events. The field is represented
 +as list of strings with core group values. Each string represents a list of
 +cores in a group. If a group is enclosed in square brackets each core is added
 +individually to a separate group (that is statistics are not aggregated).
 +Allowed formats are:
 +    0,1,2,3
 +    0-10,20-18
 +    1,3,5-8,10,0x10-12
 +    [4-15,32-63]
 +
 +If an empty string is provided as value for this field default cores
 +configuration is applied - that is separate group is created for each core.
 +
  =back
  
  =head2 Plugin C<intel_rdt>
@@@ -4311,7 -4128,7 +4311,7 @@@ Configures the base register to read fr
  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<Uint16>|B<Uint32>|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>
  
  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>,
@@@ -4323,7 -4140,10 +4323,10 @@@ significant 16E<nbsp>bits are in the re
  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>.
+ 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.
  
  =item B<RegisterCmd> B<ReadHolding>|B<ReadInput>
  
@@@ -6368,11 -6188,6 +6371,11 @@@ long string is used so that the packet 
  Sets the source address to use. I<host> may either be a numerical network
  address or a network hostname.
  
 +=item B<AddressFamily> I<af>
 +
 +Sets the address family to use. I<af> may be "any", "ipv4" or "ipv6". This
 +option will be ignored if you set a B<SourceAddress>.
 +
  =item B<Device> I<name>
  
  Sets the outgoing network device to be used. I<name> has to specify an
@@@ -7063,8 -6878,8 +7066,8 @@@ B<Synopsis:
     </Process>
     <ProcessMatch "name" "regex">
       CollectFileDescriptor false
 -     CollectContextSwitch  true
 -   </Process>
 +     CollectContextSwitch true
 +   </ProcessMatch>
   </Plugin>
  
  =over 4
@@@ -9106,12 -8921,6 +9109,12 @@@ B<Note>: I<perf> metrics can't be colle
  
  =back
  
 +=item B<PersistentNotification> B<true>|B<false>
 +Override default configuration to only send notifications when there is a change
 +in the lifecycle state of a domain. When set to true notifications will be sent
 +for every read cycle. Default is false. Does not affect the stats being
 +dispatched.
 +
  =back
  
  =head2 Plugin C<vmem>
diff --combined src/modbus.c
@@@ -80,6 -80,8 +80,8 @@@ enum mb_register_type_e /* {{{ *
    REG_TYPE_UINT16,
    REG_TYPE_UINT32,
    REG_TYPE_UINT32_CDAB,
+   REG_TYPE_UINT64,
+   REG_TYPE_INT64,
    REG_TYPE_FLOAT,
    REG_TYPE_FLOAT_CDAB }; /* }}} */
  
@@@ -135,7 -137,7 +137,7 @@@ struct mb_host_s /* {{{ *
  #else
    modbus_t *connection;
  #endif
 -  _Bool is_connected;
 +  bool is_connected;
  }; /* }}} */
  typedef struct mb_host_s mb_host_t;
  
@@@ -152,7 -154,7 +154,7 @@@ struct mb_data_group_s /* {{{ *
  /*
   * Global variables
   */
 -static mb_data_t *data_definitions = NULL;
 +static mb_data_t *data_definitions;
  
  /*
   * Functions
@@@ -332,7 -334,7 +334,7 @@@ static int mb_init_connection(mb_host_
      return status;
    }
  
 -  host->is_connected = 1;
 +  host->is_connected = true;
    return 0;
  } /* }}} int mb_init_connection */
  /* #endif LEGACY_LIBMODBUS */
@@@ -406,7 -408,7 +408,7 @@@ static int mb_init_connection(mb_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;
        (data->register_type != REG_TYPE_INT32) &&
        (data->register_type != REG_TYPE_INT32_CDAB) &&
        (data->register_type != REG_TYPE_UINT32) &&
+       (data->register_type != REG_TYPE_INT64) &&
+       (data->register_type != REG_TYPE_UINT64) &&
        (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 "
-         "is not UINT32.",
+         "is not UINT32 OR UINT64.",
          data->type, DS_TYPE_TO_STRING(ds->ds[0].type));
    }
  
        (data->register_type == REG_TYPE_FLOAT) ||
        (data->register_type == REG_TYPE_FLOAT_CDAB))
      values_num = 2;
+   else if ((data->register_type == REG_TYPE_UINT64) ||
+            (data->register_type == REG_TYPE_INT64))
+     values_num = 4;
    else
      values_num = 1;
  
      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;
      }
  
      CAST_TO_VALUE_T(ds, vt, v32);
      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);
+     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);
+     mb_submit(host, slave, data, vt);
    } else /* if (data->register_type == REG_TYPE_UINT16) */
    {
      value_t vt;
@@@ -759,6 -793,10 +793,10 @@@ static int mb_config_add_data(oconfig_i
          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;