+ Ref #520
This commit is contained in:
parent
1f8238b162
commit
7fd4e5eafa
|
@ -0,0 +1,361 @@
|
|||
#
|
||||
# Copyright 2016 Centreon (http://www.centreon.com/)
|
||||
#
|
||||
# Centreon is a full-fledged industry-strength solution that meets
|
||||
# the needs in IT infrastructure and application monitoring for
|
||||
# service performance.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
package apps::protocols::modbus::mode::numericvalue;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use List::Util qw (min max sum);
|
||||
use JSON;
|
||||
my $config_data;
|
||||
|
||||
sub custom_metric_output {
|
||||
my ($self, %options) = @_;
|
||||
my $msg;
|
||||
my $message;
|
||||
|
||||
if ($self->{result_values}->{type} eq 'unique') {
|
||||
if (defined($config_data->{selection}->{$self->{result_values}->{instance}}->{formatting}->{printf_var}) && defined($config_data->{selection}->{$self->{result_values}->{instance}}->{formatting}->{printf_msg})) {
|
||||
eval {
|
||||
local $SIG{__WARN__} = sub { $message = $_[0]; };
|
||||
local $SIG{__DIE__} = sub { $message = $_[0]; };
|
||||
$msg = sprintf("$config_data->{selection}->{$self->{result_values}->{instance}}->{formatting}->{printf_msg}",
|
||||
eval "$config_data->{selection}->{$self->{result_values}->{instance}}->{formatting}->{printf_var}");
|
||||
};
|
||||
} elsif (defined($config_data->{filters}->{formatting}->{printf_var}) && defined($config_data->{filters}->{formatting}->{printf_msg})) {
|
||||
eval {
|
||||
local $SIG{__WARN__} = sub { $message = $_[0]; };
|
||||
local $SIG{__DIE__} = sub { $message = $_[0]; };
|
||||
$msg = sprintf("$config_data->{filters}->{formatting}->{printf_msg}", eval "$config_data->{filters}->{formatting}->{printf_var}");
|
||||
};
|
||||
} else {
|
||||
$msg = sprintf("Metric '%s' value is '%s'", $self->{result_values}->{instance}, $self->{result_values}->{value});
|
||||
}
|
||||
}
|
||||
|
||||
if ($self->{result_values}->{type} eq 'global') {
|
||||
if (defined($config_data->{virtualcurve}->{$self->{result_values}->{instance}}->{formatting})) {
|
||||
eval {
|
||||
local $SIG{__WARN__} = sub { $message = $_[0]; };
|
||||
local $SIG{__DIE__} = sub { $message = $_[0]; };
|
||||
$msg = sprintf("$config_data->{virtualcurve}->{$self->{result_values}->{instance}}->{formatting}->{printf_msg}",
|
||||
eval "$config_data->{virtualcurve}->{$self->{result_values}->{instance}}->{formatting}->{printf_var}");
|
||||
};
|
||||
} elsif (defined($config_data->{formatting}->{printf_var}) && defined($config_data->{formatting}->{printf_msg})) {
|
||||
eval {
|
||||
local $SIG{__WARN__} = sub { $message = $_[0]; };
|
||||
local $SIG{__DIE__} = sub { $message = $_[0]; };
|
||||
$msg = sprintf("$config_data->{formatting}->{printf_msg}", eval "$config_data->{formatting}->{printf_var}");
|
||||
};
|
||||
} else {
|
||||
$msg = sprintf("Metric '%s' value is '%s'", $self->{result_values}->{instance}, $self->{result_values}->{value});
|
||||
}
|
||||
}
|
||||
|
||||
if (defined($message)) {
|
||||
$self->{output}->output_add(long_msg => 'printf expression problem: ' . $message);
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
|
||||
return $msg;
|
||||
|
||||
}
|
||||
|
||||
sub custom_metric_calc {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_value'};
|
||||
$self->{result_values}->{unit} = $options{new_datas}->{$self->{instance} . '_unit'};
|
||||
$self->{result_values}->{instance} = $options{new_datas}->{$self->{instance} . '_display'};
|
||||
$self->{result_values}->{type} = $options{new_datas}->{$self->{instance} . '_type'};
|
||||
$self->{result_values}->{perfdata_value} = $options{new_datas}->{$self->{instance} . '_value'};
|
||||
$self->{result_values}->{perfdata_unit} = $options{new_datas}->{$self->{instance} . '_unit'};
|
||||
$self->{result_values}->{min} = $options{new_datas}->{$self->{instance} . '_min'};
|
||||
$self->{result_values}->{max} = $options{new_datas}->{$self->{instance} . '_max'};
|
||||
|
||||
my $elem = $self->{result_values}->{type} eq 'unique' ? 'selection' : 'virtualcurve';
|
||||
my ($change_bytes_metric_selection, $change_bytes_metric_filter);
|
||||
if (defined($config_data->{filters}->{formatting}->{change_bytes})) {
|
||||
$change_bytes_metric_filter = $config_data->{filters}->{formatting}->{change_bytes};
|
||||
}
|
||||
if (defined($config_data->{$elem}->{$self->{result_values}->{instance}}->{formatting}->{change_bytes})) {
|
||||
$change_bytes_metric_selection = $config_data->{$elem}->{$self->{result_values}->{instance}}->{formatting}->{change_bytes};
|
||||
}
|
||||
|
||||
if ((defined($change_bytes_metric_selection) && $change_bytes_metric_selection) ||
|
||||
(defined($change_bytes_metric_filter) && $change_bytes_metric_filter) ||
|
||||
($config_data->{formatting}->{change_bytes} && !defined($change_bytes_metric_selection) && !defined($change_bytes_metric_filter))) {
|
||||
($self->{result_values}->{value}, $self->{result_values}->{unit}) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{value});
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub custom_metric_perfdata {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{output}->perfdata_add(label => $self->{result_values}->{instance},
|
||||
value => $self->{result_values}->{perfdata_value},
|
||||
warning => $self->{perfdata}->get_perfdata_for_output(label => ($self->{result_values}->{type} eq 'unique') ? 'warning-metric' : 'warning-global-'.$self->{result_values}->{instance}),
|
||||
critical => $self->{perfdata}->get_perfdata_for_output(label => ($self->{result_values}->{type} eq 'unique') ? 'critical-metric' : 'critical-global-'.$self->{result_values}->{instance}),
|
||||
unit => $self->{result_values}->{perfdata_unit},
|
||||
min => $self->{result_values}->{min},
|
||||
max => $self->{result_values}->{max},
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
sub custom_metric_threshold {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $label_warn = ($self->{result_values}->{type} eq 'unique') ? 'warning-metric' : 'warning-global-'.$self->{result_values}->{instance};
|
||||
my $label_crit = ($self->{result_values}->{type} eq 'unique') ? 'critical-metric' : 'critical-global-'.$self->{result_values}->{instance};
|
||||
|
||||
my $exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{perfdata_value},
|
||||
threshold => [ { label => $label_crit, exit_litteral => 'critical' },
|
||||
{ label => $label_warn, exit_litteral => 'warning' } ]);
|
||||
return $exit;
|
||||
}
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{global} = [
|
||||
{ label => 'global', set => {
|
||||
key_values => [ { name => 'value' }, { name => 'display' }, { name => 'type' }, { name => 'unit' }, { name => 'min' }, { name => 'max' } ],
|
||||
closure_custom_calc => $self->can('custom_metric_calc'),
|
||||
closure_custom_output => $self->can('custom_metric_output'),
|
||||
closure_custom_perfdata => $self->can('custom_metric_perfdata'),
|
||||
closure_custom_threshold_check => $self->can('custom_metric_threshold'),
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{metric} = [
|
||||
{ label => 'metric', set => {
|
||||
key_values => [ { name => 'value' }, { name => 'display' }, { name => 'type' }, { name => 'unit' }, { name => 'min' }, { name => 'max' } ],
|
||||
closure_custom_calc => $self->can('custom_metric_calc'),
|
||||
closure_custom_output => $self->can('custom_metric_output'),
|
||||
closure_custom_perfdata => $self->can('custom_metric_perfdata'),
|
||||
closure_custom_threshold_check => $self->can('custom_metric_threshold'),
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{version} = '1.0';
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"config:s" => { name => 'config' },
|
||||
});
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
|
||||
if (!defined($self->{option_results}->{config}) || $self->{option_results}->{config} eq '') {
|
||||
$self->{output}->add_option_msg(short_msg => "Please define --config option");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
|
||||
$config_data = $self->parse_json_config(config => $self->{option_results}->{config});
|
||||
|
||||
if (!defined($config_data->{selection})) {
|
||||
$self->{output}->add_option_msg(short_msg => "Config_error: there is no selection section in your JSON configuration !");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
|
||||
$config_data->{formatting}->{printf_msg} = "Metric '%s' value is %d" if (!exists($config_data->{formatting}->{printf_msg}));
|
||||
$config_data->{formatting}->{printf_metric_value} = "%d" if (!exists($config_data->{formatting}->{printf_metric_value}));
|
||||
$config_data->{formatting}->{custom_message_global} = "Global metrics are OK" if (!exists($config_data->{formatting}->{custom_message_global}));
|
||||
$config_data->{formatting}->{custom_message_metric} = "All metrics are OK" if (!exists($config_data->{formatting}->{custom_message_metric}));
|
||||
$config_data->{formatting}->{cannonical_separator} = "#" if (!exists($config_data->{formatting}->{cannonical_separator}));
|
||||
$config_data->{formatting}->{change_bytes} = 0 if (!exists($config_data->{formatting}->{change_bytes}));
|
||||
}
|
||||
|
||||
sub parse_json_config {
|
||||
my ($self, %options) = @_;
|
||||
my ($data, $json_text);
|
||||
|
||||
if (-f $options{config} and -r $options{config}) {
|
||||
$json_text = do {
|
||||
local $/;
|
||||
my $fh;
|
||||
if (!open($fh, "<:encoding(UTF-8)", $options{config})) {
|
||||
$self->{output}->add_option_msg(short_msg => "Can't open file $options{config}: $!");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
<$fh>;
|
||||
};
|
||||
} else {
|
||||
$json_text = $options{config};
|
||||
}
|
||||
|
||||
eval {
|
||||
$data = decode_json($json_text);
|
||||
};
|
||||
if ($@) {
|
||||
$self->{output}->add_option_msg(short_msg => "Cannot decode json config file: $@");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
return $data
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{metrics} = {};
|
||||
$self->{vmetrics} = {};
|
||||
$self->{metric} = {};
|
||||
$self->{global} = {};
|
||||
|
||||
if (defined($config_data->{virtualcurve})) {
|
||||
push @{$self->{maps_counters_type}}, {
|
||||
name => 'global', type => 1, message_separator => $config_data->{formatting}->{message_separator}, message_multiple => $config_data->{formatting}->{custom_message_global},
|
||||
};
|
||||
}
|
||||
|
||||
if (defined($config_data->{selection})) {
|
||||
push @{$self->{maps_counters_type}}, {
|
||||
name => 'metric', type => 1, message_separator => $config_data->{formatting}->{message_separator}, message_multiple => $config_data->{formatting}->{custom_message_metric},
|
||||
};
|
||||
foreach my $id (keys %{$config_data->{selection}}) {
|
||||
next if (!defined($config_data->{selection}->{id}->{address}));
|
||||
my $results = $options{custom}->read_objects(address => $config_data->{selection}->{id}->{address},
|
||||
unit => $config_data->{selection}->{id}->{unit}, quantity => $config_data->{selection}->{id}->{quantity});
|
||||
my $i = 0;
|
||||
foreach (@{$results}) {
|
||||
my $metric_key = $id . '.' . $i;
|
||||
$self->{metrics}->{$metric_key} = { name => $_->{metric_name} };
|
||||
$self->{metrics}->{$metric_key}->{display_name} = $id;
|
||||
$self->{metrics}->{$metric_key}->{current} = $_->{current_value};
|
||||
$self->{metrics}->{$metric_key}->{unit} = defined($_->{unit_name}) ? $_->{unit_name} : '';
|
||||
$self->{metrics}->{$metric_key}->{min} = defined($_->{min}) ? $_->{min} : '';
|
||||
$self->{metrics}->{$metric_key}->{max} = defined($_->{max}) ? $_->{max} : '';
|
||||
$self->{metrics}->{$metric_key}->{display} = (defined($_->{display}) && $_->{display}) ? 1 : 0;
|
||||
$i++;
|
||||
|
||||
$self->{metric}->{$metric_key} = {display => $self->{metrics}->{$metric_key}->{display_name},
|
||||
type => 'unique',
|
||||
unit => $self->{metrics}->{$metric_key}->{unit},
|
||||
value => $self->{metrics}->{$metric_key}->{current},
|
||||
min => $self->{metrics}->{$metric_key}->{min},
|
||||
max => $self->{metrics}->{$metric_key}->{max} } if ($self->{metrics}->{$metric_key}->{display} == 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach my $vcurve (keys %{$config_data->{virtualcurve}}) {
|
||||
foreach my $metric (keys %{$self->{metrics}}) {
|
||||
$self->{vmetrics}->{$vcurve}->{values} = [] if (!defined($self->{vmetrics}->{$vcurve}));
|
||||
if (defined($config_data->{virtualcurve}->{$vcurve}->{pattern}) && $config_data->{virtualcurve}->{$vcurve}->{pattern} ne '') {
|
||||
push (@{$self->{vmetrics}->{$vcurve}->{values}}, $self->{metrics}->{$metric}->{current}) if ($self->{metrics}->{$metric}->{name} =~ /$config_data->{virtualcurve}{$vcurve}->{pattern}/);
|
||||
} else {
|
||||
push (@{$self->{vmetrics}->{$vcurve}->{values}}, $self->{metrics}->{$metric}->{current});
|
||||
}
|
||||
}
|
||||
|
||||
next if (!defined($self->{vmetrics}->{$vcurve}->{values}) || scalar(@{$self->{vmetrics}->{$vcurve}->{values}}) == 0);
|
||||
|
||||
$self->{vmetrics}->{$vcurve}->{aggregated_value} = sprintf($config_data->{formatting}->{printf_metric_value},
|
||||
sum(@{$self->{vmetrics}->{$vcurve}->{values}}) / scalar(@{$self->{vmetrics}->{$vcurve}->{values}})) if ($config_data->{virtualcurve}->{$vcurve}->{aggregation} eq 'avg');
|
||||
$self->{vmetrics}->{$vcurve}->{aggregated_value} = sprintf($config_data->{formatting}->{printf_metric_value},
|
||||
sum(@{$self->{vmetrics}->{$vcurve}->{values}})) if ($config_data->{virtualcurve}->{$vcurve}->{aggregation} eq 'sum');
|
||||
$self->{vmetrics}->{$vcurve}->{aggregated_value} = sprintf($config_data->{formatting}->{printf_metric_value},
|
||||
min(@{$self->{vmetrics}->{$vcurve}->{values}})) if ($config_data->{virtualcurve}->{$vcurve}->{aggregation} eq 'min');
|
||||
$self->{vmetrics}->{$vcurve}->{aggregated_value} = sprintf($config_data->{formatting}->{printf_metric_value},
|
||||
max(@{$self->{vmetrics}->{$vcurve}->{values}})) if ($config_data->{virtualcurve}->{$vcurve}->{aggregation} eq 'max');
|
||||
$self->{vmetrics}->{$vcurve}->{aggregated_value} = eval "$self->{vmetrics}->{$vcurve}->{aggregated_value} $config_data->{virtualcurve}->{$vcurve}->{custom}" if (defined($config_data->{virtualcurve}->{$vcurve}->{custom}));
|
||||
|
||||
$self->{vmetrics}->{$vcurve}->{unit} = (defined($config_data->{virtualcurve}->{$vcurve}->{unit})) ? $config_data->{virtualcurve}->{$vcurve}->{unit} : '';
|
||||
$self->{vmetrics}->{$vcurve}->{min} = (defined($config_data->{virtualcurve}->{$vcurve}->{min})) ? $config_data->{virtualcurve}->{$vcurve}->{min} : '';
|
||||
$self->{vmetrics}->{$vcurve}->{max} = (defined($config_data->{virtualcurve}->{$vcurve}->{max})) ? $config_data->{virtualcurve}->{$vcurve}->{max} : '';
|
||||
|
||||
if (defined($self->{option_results}->{'warning-global'}) || defined($config_data->{virtualcurve}->{$vcurve}->{warning})) {
|
||||
$self->{perfdata}->threshold_validate(label => 'warning-global-' . $vcurve,
|
||||
value => (defined($self->{option_results}->{'warning-global'})) ? $self->{option_results}->{'warning-global'} : $config_data->{virtualcurve}->{$vcurve}->{warning});
|
||||
}
|
||||
if (defined($self->{option_results}->{'critical-global'}) || defined($config_data->{virtualcurve}->{$vcurve}->{critical})) {
|
||||
$self->{perfdata}->threshold_validate(label => 'critical-global-' . $vcurve,
|
||||
value => (defined($self->{option_results}->{'critical-global'})) ? $self->{option_results}->{'critical-global'} : $config_data->{virtualcurve}->{$vcurve}->{critical});
|
||||
}
|
||||
|
||||
$self->{global}->{$vcurve} = {
|
||||
display => $vcurve,
|
||||
type => 'global',
|
||||
unit => $self->{vmetrics}->{$vcurve}->{unit},
|
||||
value => $self->{vmetrics}->{$vcurve}->{aggregated_value},
|
||||
min => $self->{vmetrics}->{$vcurve}->{min},
|
||||
max => $self->{vmetrics}->{$vcurve}->{max}
|
||||
};
|
||||
}
|
||||
|
||||
if (scalar(keys %{$self->{metric}}) <= 0 && scalar(keys %{$self->{global}}) <= 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "No metrics returned - are your selection correct ?");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
}
|
||||
|
||||
1
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Mode to play with modbus metrics
|
||||
e.g: display two curves of different service on the same graph
|
||||
e.g: aggregate multiple metrics (min,max,avg,sum) or custom operation
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--config>
|
||||
|
||||
Specify the config (can be a file or a json string directly).
|
||||
|
||||
=item B<--filter-counters>
|
||||
|
||||
Filter some counter (can be 'unique' or 'global')
|
||||
Useless, if you use selection/filter but not
|
||||
global/virtual curves
|
||||
|
||||
=item B<--warning-*>
|
||||
|
||||
Warning threshold (can be 'unique' or 'global')
|
||||
(Override config if set)
|
||||
|
||||
=item B<--critical-*>
|
||||
|
||||
Critical threshold (can be 'unique' or 'global')
|
||||
(Override config if set)
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,49 @@
|
|||
#
|
||||
# Copyright 2017 Centreon (http://www.centreon.com/)
|
||||
#
|
||||
# Centreon is a full-fledged industry-strength solution that meets
|
||||
# the needs in IT infrastructure and application monitoring for
|
||||
# service performance.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
package apps::protocols::modbus::plugin;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use base qw(centreon::plugins::script_custom);
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{version} = '0.1';
|
||||
%{$self->{modes}} = (
|
||||
'numeric-value' => 'apps::protocols::modbus::mode::numericvalue',
|
||||
);
|
||||
|
||||
$self->{custom_modes}{api} = 'centreon::common::protocols::modbus::custom::api';
|
||||
return $self;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 PLUGIN DESCRIPTION
|
||||
|
||||
Generic Modbus plugin.
|
||||
|
||||
=cut
|
|
@ -0,0 +1,234 @@
|
|||
#
|
||||
# Copyright 2017 Centreon (http://www.centreon.com/)
|
||||
#
|
||||
# Centreon is a full-fledged industry-strength solution that meets
|
||||
# the needs in IT infrastructure and application monitoring for
|
||||
# service performance.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
package centreon::common::protocols::modbus::custom::api;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use centreon::plugins::misc;
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = {};
|
||||
bless $self, $class;
|
||||
|
||||
if (!defined($options{output})) {
|
||||
print "Class Custom: Need to specify 'output' argument.\n";
|
||||
exit 3;
|
||||
}
|
||||
if (!defined($options{options})) {
|
||||
$options{output}->add_option_msg(short_msg => "Class Custom: Need to specify 'options' argument.");
|
||||
$options{output}->option_exit();
|
||||
}
|
||||
|
||||
if (!defined($options{noptions})) {
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"rtu-port:s@" => { name => 'rtu_port' },
|
||||
"rtu-baudrate:s@" => { name => 'rtu_baudrate' },
|
||||
"rtu-databits:s@" => { name => 'rtu_databits' },
|
||||
"rtu-parity:s@" => { name => 'rtu_parity' },
|
||||
"rtu-stopbits:s@" => { name => 'rtu_stopbits' },
|
||||
"tcp-host:s@" => { name => 'tcp_host' },
|
||||
"tcp-port:s@" => { name => 'tcp_port' },
|
||||
"timeout:s@" => { name => 'timeout' },
|
||||
});
|
||||
}
|
||||
$options{options}->add_help(package => __PACKAGE__, sections => 'MODBUS OPTIONS', once => 1);
|
||||
|
||||
$self->{output} = $options{output};
|
||||
$self->{mode} = $options{mode};
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub set_options {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{option_results} = $options{option_results};
|
||||
# We remove empty rtu_port and tcp_host
|
||||
foreach my $label ('rtu_port', 'tcp_host') {
|
||||
if (defined($self->{option_results}->{$label})) {
|
||||
my @del_indexes = reverse(grep { $self->{option_results}->{$label}->[$_] eq '' } 0..$#{$self->{option_results}->{$label}});
|
||||
foreach my $item (@del_indexes) {
|
||||
splice (@{$self->{option_results}->{$label}}, $item, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub set_defaults {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
foreach (keys %{$options{default}}) {
|
||||
if ($_ eq $self->{mode}) {
|
||||
for (my $i = 0; $i < scalar(@{$options{default}->{$_}}); $i++) {
|
||||
foreach my $opt (keys %{$options{default}->{$_}[$i]}) {
|
||||
if (!defined($self->{option_results}->{$opt}[$i])) {
|
||||
$self->{option_results}->{$opt}[$i] = $options{default}->{$_}[$i]->{$opt};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{modbus_type} = 1;
|
||||
$self->{modbus_params} = { rtu => {} , tcp => {} };
|
||||
my $timeout = (defined($self->{option_results}->{timeout})) ? shift(@{$self->{option_results}->{timeout}}) : 10;
|
||||
|
||||
if (defined($self->{option_results}->{rtu_port}->[0])) {
|
||||
$self->{modbus_type} = 2;
|
||||
$self->{modbus_params}->{rtu}->{port} = shift(@{$self->{option_results}->{rtu_port}});
|
||||
$self->{modbus_params}->{rtu}->{baudrate} = (defined($self->{option_results}->{rtu_baudrate})) ? shift(@{$self->{option_results}->{rtu_baudrate}}) : 9600;
|
||||
$self->{modbus_params}->{rtu}->{databits} = (defined($self->{option_results}->{rtu_databits})) ? shift(@{$self->{option_results}->{rtu_databits}}) : 8;
|
||||
$self->{modbus_params}->{rtu}->{parity} = (defined($self->{option_results}->{rtu_parity})) ? shift(@{$self->{option_results}->{rtu_parity}}) : 'none';
|
||||
$self->{modbus_params}->{rtu}->{stopbits} = (defined($self->{option_results}->{rtu_stopbits})) ? shift(@{$self->{option_results}->{rtu_stopbits}}) : 1;
|
||||
$self->{modbus_params}->{rtu}->{timeout} = $timeout;
|
||||
} elsif (defined($self->{option_results}->{tcp_host}->[0])) {
|
||||
$self->{modbus_params}->{tcp}->{host} = shift(@{$self->{option_results}->{tcp_host}});
|
||||
$self->{modbus_params}->{tcp}->{port} = (defined($self->{option_results}->{tcp_port})) ? shift(@{$self->{option_results}->{tcp_port}}) : 502;
|
||||
$self->{modbus_params}->{tcp}->{timeout} = $timeout;
|
||||
} else {
|
||||
$self->{output}->add_option_msg(short_msg => "Need to specify --rtu-port or --tcp-host option.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
|
||||
if ((!defined($self->{modbus_params}->{rtu}->{port}) || scalar(@{$self->{option_results}->{rtu_port}}) == 0) &&
|
||||
(!defined($self->{modbus_params}->{tcp}->{host}) || scalar(@{$self->{option_results}->{tcp_host}}) == 0)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub connect {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
if ($self->{modbus_type} == 1) {
|
||||
centreon::plugins::misc::mymodule_load(output => $self->{output}, module => 'Device::Modbus::TCP::Client',
|
||||
error_msg => "Cannot load module 'Device::Modbus::TCP::Client'.");
|
||||
$self->{modbus_client} = new evice::Modbus::TCP::Client->new(%{$self->{modbus_params}->{tcp}});
|
||||
} else {
|
||||
centreon::plugins::misc::mymodule_load(output => $self->{output}, module => 'Device::Modbus::RTU::Client',
|
||||
error_msg => "Cannot load module 'Device::Modbus::RTU::Client'.");
|
||||
$self->{modbus_client} = new evice::Modbus::RTU::Client->new(%{$self->{modbus_params}->{rtu}});
|
||||
}
|
||||
}
|
||||
|
||||
my %mapping_methods = (
|
||||
holding => 'read_holding_registers',
|
||||
coils => 'read_coils',
|
||||
discrete => 'read_discrete_inputs',
|
||||
input => 'read_input_registers',
|
||||
);
|
||||
|
||||
sub read_objects {
|
||||
my ($self, %options) = @_;
|
||||
my $unit = defined($options{unit}) ? $options{unit} : 1;
|
||||
my $type = defined($options{type}) ? $options{type} : 'holding';
|
||||
my $quantity = defined($options{quantity}) ? $options{quantity} : 1;
|
||||
my $results = [];
|
||||
|
||||
if (!defined($self->{modbus_client})) {
|
||||
$self->connect();
|
||||
}
|
||||
|
||||
my $method = $self->{modbus_client}->can($mapping_methods{$type});
|
||||
if ($method) {
|
||||
my $req = $self->{modbus_client}->$method(unit => $unit, address => $options{address}, quantity => $quantity);
|
||||
if (!$self->{modbus_client}->send_request($req)) {
|
||||
$self->{output}->add_option_msg(short_msg => "Modbus Request: send error $!");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
my $response = $self->{modbus_client}->receive_response;
|
||||
if ($response->success()) {
|
||||
$results = $response->values();
|
||||
} else {
|
||||
$self->{output}->add_option_msg(short_msg => "Modbus Request: error " . $response->message()->stringify());
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
}
|
||||
|
||||
if (scalar(@{$results}) == 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "Modbus Request: Cant get a single value.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Modbus connector library
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my modbus connector
|
||||
|
||||
=head1 MODBUS OPTIONS
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--rtu-port>
|
||||
|
||||
The serial port to open.
|
||||
Example: --rtu-port=/dev/ttyUSB0
|
||||
|
||||
=item B<--rtu-baudrate>
|
||||
|
||||
A valid baud rate (Default: 9600)
|
||||
|
||||
=item B<--rtu-databits>
|
||||
|
||||
An integer from 5 to 8 (Default: 8)
|
||||
|
||||
=item B<--rtu-parity>
|
||||
|
||||
Either 'even', 'odd' or 'none' (Default: none)
|
||||
|
||||
=item B<--rtu-stopbits>
|
||||
|
||||
1 or 2 (Default: 1)
|
||||
|
||||
=item B<--tcp-host>
|
||||
|
||||
Host address
|
||||
|
||||
=item B<--tcp-port>
|
||||
|
||||
Host port (Default: 502)
|
||||
|
||||
=item B<--timeout>
|
||||
|
||||
Timeout in seconds (Default: 10)
|
||||
|
||||
=back
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
B<custom>.
|
||||
|
||||
=cut
|
Loading…
Reference in New Issue