diff --git a/src/hardware/sensors/hwgste/snmp/mode/components/co2.pm b/src/hardware/sensors/hwgste/snmp/mode/components/co2.pm new file mode 100644 index 0000000000..4e5f722a62 --- /dev/null +++ b/src/hardware/sensors/hwgste/snmp/mode/components/co2.pm @@ -0,0 +1,157 @@ +package hardware::sensors::hwgste::snmp::mode::components::co2; + +use strict; +use warnings; + +use hardware::sensors::hwgste::snmp::mode::components::resources qw($mapping); + +sub load {} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking co2"); + $self->{components}->{co2} = { + name => 'co2', + total => 0, + skip => 0 + }; + + return if ($self->check_filter(section => 'co2')); + + foreach my $oid ( + $self->{snmp}->oid_lex_sort( + keys %{ + $self->{results}->{ + $mapping->{branch_sensors}->{$self->{branch}} + } + } + ) + ) { + next if ( + $oid !~ + /^$mapping->{$self->{branch}}->{sensState}->{oid}\.(.*)$/ + ); + + my $instance = $1; + + my $result = $self->{snmp}->map_instance( + mapping => $mapping->{$self->{branch}}, + results => $self->{results}->{ + $mapping->{branch_sensors}->{$self->{branch}} + }, + instance => $instance + ); + + # + # STE2 Plus: + # CO2 sensors have: + # unit = 0 => '' + # name contains CO2 + # + next if ( + !defined($result->{sensUnit}) + || $result->{sensUnit} ne '' + ); + + next if ( + !defined($result->{sensName}) + || $result->{sensName} !~ /CO2/i + ); + + next if ( + $self->check_filter( + section => 'co2', + instance => $instance + ) + ); + + $self->{components}->{co2}->{total}++; + + # + # STE2 returns value * 10 + # + if ( + defined($result->{sensValue}) + && $result->{sensValue} =~ /^-?\d+(?:\.\d+)?$/ + ) { + $result->{sensValue} /= 10; + } + + $self->{output}->output_add( + long_msg => sprintf( + "co2 '%s' state is '%s' [instance: %s, value: %s ppm]", + $result->{sensName}, + $result->{sensState}, + $instance, + $result->{sensValue} + ) + ); + + my $exit = $self->get_severity( + section => 'co2', + label => 'default', + instance => $instance, + value => $result->{sensState} + ); + + if ( + !$self->{output}->is_status( + value => $exit, + compare => 'ok', + litteral => 1 + ) + ) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf( + "co2 '%s' state is '%s'", + $result->{sensName}, + $result->{sensState} + ) + ); + } + + if ( + defined($result->{sensValue}) + && $result->{sensValue} =~ /^-?\d+(?:\.\d+)?$/ + ) { + my ($exit2, $warn, $crit, $checked) = + $self->get_severity_numeric( + section => 'co2', + instance => $instance, + value => $result->{sensValue} + ); + + if ( + !$self->{output}->is_status( + value => $exit2, + compare => 'ok', + litteral => 1 + ) + ) { + $self->{output}->output_add( + severity => $exit2, + short_msg => sprintf( + "co2 '%s' value is %s ppm", + $result->{sensName}, + $result->{sensValue} + ) + ); + } + + $self->{output}->perfdata_add( + label => 'sensor', + unit => 'ppm', + nlabel => 'hardware.sensor.co2.ppm', + instances => $result->{sensName}, + value => $result->{sensValue}, + warning => $warn, + critical => $crit, + min => 0 + ); + } + } +} + +1; diff --git a/src/hardware/sensors/hwgste/snmp/mode/components/resources.pm b/src/hardware/sensors/hwgste/snmp/mode/components/resources.pm index 41314da7d8..822c0fce5e 100644 --- a/src/hardware/sensors/hwgste/snmp/mode/components/resources.pm +++ b/src/hardware/sensors/hwgste/snmp/mode/components/resources.pm @@ -45,6 +45,7 @@ our @EXPORT_OK = qw($mapping); 2 => 'F', 3 => 'K', 4 => '%', + 5 => 'water', ); $mapping = { diff --git a/src/hardware/sensors/hwgste/snmp/mode/components/water.pm b/src/hardware/sensors/hwgste/snmp/mode/components/water.pm new file mode 100644 index 0000000000..ab1067aec3 --- /dev/null +++ b/src/hardware/sensors/hwgste/snmp/mode/components/water.pm @@ -0,0 +1,94 @@ +package hardware::sensors::hwgste::snmp::mode::components::water; + +use strict; +use warnings; + +use hardware::sensors::hwgste::snmp::mode::components::resources qw($mapping); + +sub load {} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking water"); + + $self->{components}->{water} = { + name => 'water', + total => 0, + skip => 0 + }; + + return if ($self->check_filter(section => 'water')); + + foreach my $oid ( + $self->{snmp}->oid_lex_sort( + keys %{ + $self->{results}->{ + $mapping->{branch_sensors}->{$self->{branch}} + } + } + ) + ) { + next if ( + $oid !~ + /^$mapping->{$self->{branch}}->{sensState}->{oid}\.(.*)$/ + ); + + my $instance = $1; + + my $result = $self->{snmp}->map_instance( + mapping => $mapping->{$self->{branch}}, + results => $self->{results}->{ + $mapping->{branch_sensors}->{$self->{branch}} + }, + instance => $instance + ); + + # + # STE2 Plus water leak sensor: + # unit = 5 => water + # + next if ( + !defined($result->{sensUnit}) + || $result->{sensUnit} ne 'water' + ); + + # + # Accept common naming conventions + # + next if ( + !defined($result->{sensName}) + || $result->{sensName} !~ /(?:WATER|FLOOD|LEAK)/i + ); + + next if ( + $self->check_filter( + section => 'water', + instance => $instance + ) + ); + + $self->{components}->{water}->{total}++; + + my $value = defined($result->{sensValue}) + ? $result->{sensValue} + : 'unknown'; + + $self->{output}->output_add( + long_msg => sprintf( + "water sensor '%s' state is '%s' [instance: %s, value: %s]", + $result->{sensName}, + $result->{sensState}, + $instance, + $value + ) + ); + + # + # Water leak detector is binary: + # normal => OK + # anything else => CRITICAL + # + my $exit = 'OK'; + + if ($result->{sensState} diff --git a/src/hardware/sensors/hwgste/snmp/mode/sensors.pm b/src/hardware/sensors/hwgste/snmp/mode/sensors.pm index e3d807733b..158335a6fb 100644 --- a/src/hardware/sensors/hwgste/snmp/mode/sensors.pm +++ b/src/hardware/sensors/hwgste/snmp/mode/sensors.pm @@ -24,15 +24,17 @@ use base qw(centreon::plugins::templates::hardware); use strict; use warnings; + use hardware::sensors::hwgste::snmp::mode::components::resources qw($mapping); sub set_system { my ($self, %options) = @_; - $self->{regexp_threshold_numeric_check_section_option} = '^(temperature|humidity)$'; - + $self->{regexp_threshold_numeric_check_section_option} = + '^(temperature|humidity|co2)$'; + $self->{cb_hook2} = 'snmp_execute'; - + $self->{thresholds} = { default => [ ['invalid', 'UNKNOWN'], @@ -44,27 +46,59 @@ sub set_system { ] }; - $self->{components_path} = 'hardware::sensors::hwgste::snmp::mode::components'; - $self->{components_module} = ['temperature', 'humidity']; + $self->{components_path} = + 'hardware::sensors::hwgste::snmp::mode::components'; + + $self->{components_module} = [ + 'temperature', + 'humidity', + 'co2', + 'water' + ]; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; + $self->{results} = $self->{snmp}->get_multiple_table( - oids => [{ oid => $mapping->{branch_sensors}->{hwgste} }, { oid => $mapping->{branch_sensors}->{hwgste2} }] + oids => [ + { oid => $mapping->{branch_sensors}->{hwgste} }, + { oid => $mapping->{branch_sensors}->{hwgste2} } + ] ); + $self->{branch} = 'hwgste'; - if (defined($self->{results}->{ $mapping->{branch_sensors}->{hwgste2} }) && - scalar(keys %{$self->{results}->{ $mapping->{branch_sensors}->{hwgste2} }}) > 0) { + + if ( + defined( + $self->{results}->{ + $mapping->{branch_sensors}->{hwgste2} + } + ) + && + scalar( + keys %{ + $self->{results}->{ + $mapping->{branch_sensors}->{hwgste2} + } + } + ) > 0 + ) { $self->{branch} = 'hwgste2'; } } sub new { my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_absent => 1); + + my $self = $class->SUPER::new( + package => __PACKAGE__, + %options, + no_absent => 1 + ); + bless $self, $class; $options{options}->add_options(arguments => {}); @@ -74,8 +108,6 @@ sub new { 1; -__END__ - =head1 MODE Check HWg-STE sensors. @@ -85,40 +117,36 @@ Check HWg-STE sensors. =item B<--component> Which component to check (default: '.*'). -Can be: 'temperature', 'humidity'. + +Can be: +'temperature', +'humidity', +'co2', +'water'. =item B<--filter> Exclude some parts. -You can also exclude items from specific instances: --filter=sensor,10 - -=item B<--absent-problem> - -Return an error if a component is not 'present' (default is skipping). -It can be set globally or for a specific instance: --absent-problem='component_name' or --absent-problem='component_name,instance_value'. -=item B<--threshold-overload> +You can also exclude items from specific instances: -Use this option to override the status returned by the plugin when the status label matches a regular expression (syntax: section,[instance,]status,regexp). -Example: --threshold-overload='sensor,CRITICAL,^(?!(normal)$)' + --filter=temperature,2 =item B<--warning> -Set warning threshold for temperature, humidity (syntax: type,instance,threshold) -Example: --warning='temperature,.*,30' +Numeric warning thresholds available for: -=item B<--critical> - -Set critical threshold for temperature, humidity (syntax: type,instance,threshold) -Example: --critical='humidty,.*,40' + temperature + humidity + co2 -=item B<--warning-count-*> - -Define the warning threshold for the number of components of one type (replace '*' with the component type). +=item B<--critical> -=item B<--critical-count-*> +Numeric critical thresholds available for: -Define the critical threshold for the number of components of one type (replace '*' with the component type). + temperature + humidity + co2 =back