From 92a928be9c01cdc6826287f3bb69a1ae3536c2b5 Mon Sep 17 00:00:00 2001
From: qgarnier <garnier.quentin@gmail.com>
Date: Mon, 5 Dec 2022 14:06:30 +0000
Subject: [PATCH] (plugin) hardware::sensors::apc::snmp - new (#4073)

---
 .../sensors/apc/snmp/mode/components/fluid.pm | 104 ++++++++
 .../apc/snmp/mode/components/humidity.pm      | 236 ++++++++++++++++++
 .../apc/snmp/mode/components/resources.pm     |  64 +++++
 .../apc/snmp/mode/components/temperature.pm   | 235 +++++++++++++++++
 .../hardware/sensors/apc/snmp/mode/sensors.pm | 127 ++++++++++
 .../hardware/sensors/apc/snmp/plugin.pm       |  47 ++++
 6 files changed, 813 insertions(+)
 create mode 100644 centreon-plugins/hardware/sensors/apc/snmp/mode/components/fluid.pm
 create mode 100644 centreon-plugins/hardware/sensors/apc/snmp/mode/components/humidity.pm
 create mode 100644 centreon-plugins/hardware/sensors/apc/snmp/mode/components/resources.pm
 create mode 100644 centreon-plugins/hardware/sensors/apc/snmp/mode/components/temperature.pm
 create mode 100644 centreon-plugins/hardware/sensors/apc/snmp/mode/sensors.pm
 create mode 100644 centreon-plugins/hardware/sensors/apc/snmp/plugin.pm

diff --git a/centreon-plugins/hardware/sensors/apc/snmp/mode/components/fluid.pm b/centreon-plugins/hardware/sensors/apc/snmp/mode/components/fluid.pm
new file mode 100644
index 000000000..fe029c5a5
--- /dev/null
+++ b/centreon-plugins/hardware/sensors/apc/snmp/mode/components/fluid.pm
@@ -0,0 +1,104 @@
+#
+# Copyright 2022 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 hardware::sensors::apc::snmp::mode::components::fluid;
+
+use strict;
+use warnings;
+use hardware::sensors::apc::snmp::mode::components::resources qw($map_alarm_status $map_comm_status2 $map_fluid_state);
+
+sub load {}
+
+sub check_module_fluid {
+    my ($self) = @_;
+
+    my $oid_memFluidSensorStatusTable = '.1.3.6.1.4.1.318.1.1.10.4.7.6';
+    my $mapping = {
+        name        => { oid => '.1.3.6.1.4.1.318.1.1.10.4.7.6.1.3' }, # memFluidSensorStatusSensorName
+        state       => { oid => '.1.3.6.1.4.1.318.1.1.10.4.7.6.1.5', map => $map_fluid_state }, # memFluidSensorStatusSensorState
+        alarmStatus => { oid => '.1.3.6.1.4.1.318.1.1.10.4.7.6.1.7', map => $map_alarm_status }, # memFluidStatusAlarmStatus
+        commStatus  => { oid => '.1.3.6.1.4.1.318.1.1.10.4.7.6.1.8', map => $map_comm_status2 } # memFluidSensorCommStatus
+    };
+
+    my $snmp_result = $self->{snmp}->get_table(oid => $oid_memFluidSensorStatusTable);
+
+    foreach my $oid ($self->{snmp}->oid_lex_sort(keys %$snmp_result)) {
+        next if ($oid !~ /^$mapping->{alarmStatus}->{oid}\.(\d+)\.(\d+)$/);
+
+        my $module_name = $self->{modules_name}->{$1};
+        my $instance = $1 . '.' . $2;
+        my $result = $self->{snmp}->map_instance(
+            mapping => $mapping,
+            results => $snmp_result,
+            instance => $instance
+        );
+
+        next if ($self->check_filter(section => 'fluid', instance => $instance));
+        $self->{components}->{fluid}->{total}++;
+
+        my $name = $module_name . ':' . $result->{name};
+        $self->{output}->output_add(
+            long_msg => sprintf(
+                "fluid '%s' alarm status is %s [instance: %s] [state: %s] [comm: %s]",
+                $name,
+                $result->{alarmStatus},
+                $instance, 
+                $result->{state},
+                $result->{commStatus}
+            )
+        );
+
+        my $exit = $self->get_severity(label => 'default', section => 'fluid.alarm', value => $result->{alarmStatus});
+        if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
+            $self->{output}->output_add(
+                severity => $exit,
+                short_msg => sprintf(
+                    "Fluid '%s' alarm status is %s",
+                    $name,
+                    $result->{alarmStatus}
+                )
+            );
+        }
+
+        $exit = $self->get_severity(label => 'default', section => 'fluid.comm', value => $result->{commStatus});
+        if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
+            $self->{output}->output_add(
+                severity => $exit,
+                short_msg => sprintf(
+                    "Fluid '%s' communication status is %s",
+                    $name,
+                    $result->{commStatus}
+                )
+            );
+        }
+    }
+}
+
+sub check {
+    my ($self) = @_;
+
+    $self->{output}->output_add(long_msg => "Checking fluids");
+    $self->{components}->{fluid} = { name => 'fluid', total => 0, skip => 0 };
+    return if ($self->check_filter(section => 'fluid'));
+
+    check_module_fluid($self);
+}
+
+1;
diff --git a/centreon-plugins/hardware/sensors/apc/snmp/mode/components/humidity.pm b/centreon-plugins/hardware/sensors/apc/snmp/mode/components/humidity.pm
new file mode 100644
index 000000000..f37e8c090
--- /dev/null
+++ b/centreon-plugins/hardware/sensors/apc/snmp/mode/components/humidity.pm
@@ -0,0 +1,236 @@
+#
+# Copyright 2022 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 hardware::sensors::apc::snmp::mode::components::humidity;
+
+use strict;
+use warnings;
+use hardware::sensors::apc::snmp::mode::components::resources qw($map_alarm_status $map_comm_status $map_comm_status3);
+
+sub load {}
+
+sub check_module_humidity {
+    my ($self) = @_;
+
+    my $oid_memSensorsStatusTable = '.1.3.6.1.4.1.318.1.1.10.4.2.3';
+    my $mapping = {
+        name        => { oid => '.1.3.6.1.4.1.318.1.1.10.4.2.3.1.3' }, # memSensorsStatusSensorName
+        humidity    => { oid => '.1.3.6.1.4.1.318.1.1.10.4.2.3.1.6' }, # memSensorsHumidity
+        commStatus  => { oid => '.1.3.6.1.4.1.318.1.1.10.4.2.3.1.7', map => $map_comm_status }, # memSensorsCommStatus
+        alarmStatus => { oid => '.1.3.6.1.4.1.318.1.1.10.4.2.3.1.8', map => $map_alarm_status } # memSensorsAlarmStatus
+    };
+
+    my $snmp_result = $self->{snmp_module_sensors};
+    if ($self->{checked_module_sensors} == 0) {
+        $self->{snmp_module_sensors} = $self->{snmp}->get_table(oid => $oid_memSensorsStatusTable);
+        $self->{checked_module_sensors} = 1;
+    }
+
+    foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{snmp_module_sensors}})) {
+        next if ($oid !~ /^$mapping->{alarmStatus}->{oid}\.(\d+)\.(\d+)$/);
+
+        my $module_name = $self->{modules_name}->{$1};
+        my $instance = $1 . '.' . $2;
+        my $result = $self->{snmp}->map_instance(
+            mapping => $mapping,
+            results => $self->{snmp_module_sensors},
+            instance => $instance
+        );
+
+        $instance = 'module.' . $instance;
+
+        next if ($self->check_filter(section => 'humidity', instance => $instance));
+        $self->{components}->{temperature}->{total}++;
+
+        my $name = $module_name . ':' . $result->{name};
+        $self->{output}->output_add(
+            long_msg => sprintf(
+                "humidity '%s' alarm status is %s [instance: %s] [value: %s] [comm: %s]",
+                $name,
+                $result->{alarmStatus},
+                $instance, 
+                $result->{humidity},
+                $result->{commStatus}
+            )
+        );
+
+        my $exit = $self->get_severity(label => 'default', section => 'humidity.alarm', value => $result->{alarmStatus});
+        if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
+            $self->{output}->output_add(
+                severity => $exit,
+                short_msg => sprintf(
+                    "Humidity '%s' alarm status is %s",
+                    $name,
+                    $result->{alarmStatus}
+                )
+            );
+        }
+
+        $exit = $self->get_severity(label => 'default', section => 'humidity.comm', value => $result->{commStatus});
+        if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
+            $self->{output}->output_add(
+                severity => $exit,
+                short_msg => sprintf(
+                    "Humidity '%s' communication status is %s",
+                    $name,
+                    $result->{commStatus}
+                )
+            );
+        }
+
+        my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'humidity', instance => $instance, value => $result->{temp});
+        if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) {
+            $self->{output}->output_add(
+                severity => $exit2,
+                short_msg => sprintf(
+                    "Humidity '%s' is %s %%",
+                    $name,
+                    $result->{humidity}
+                )
+            );
+        }
+
+        $self->{output}->perfdata_add(
+            nlabel => 'hardware.sensor.humidity.percentage',
+            unit => '%',
+            instances => $name,
+            value => $result->{humidity},
+            warning => $warn,
+            critical => $crit,
+            min => 0,
+            max => 100
+        );
+    }
+}
+
+sub check_wireless_humidity {
+    my ($self) = @_;
+
+    my $oid_wirelessSensorStatusTable = '.1.3.6.1.4.1.318.1.1.10.5.1.1';
+    my $oid_wirelessSensorStatusMinHumidityThresh = '.1.3.6.1.4.1.318.1.1.10.5.1.1.1.15';
+    my $mapping = {
+        name        => { oid => '.1.3.6.1.4.1.318.1.1.10.5.1.1.1.3' }, # wirelessSensorStatusName
+        humidity    => { oid => '.1.3.6.1.4.1.318.1.1.10.5.1.1.1.8' }, # wirelessSensorStatusHumidity
+        highWarn    => { oid => '.1.3.6.1.4.1.318.1.1.10.5.1.1.1.9' }, # wirelessSensorStatusHighHumidityThresh
+        lowWarn     => { oid => '.1.3.6.1.4.1.318.1.1.10.5.1.1.1.10' }, # wirelessSensorStatusLowHumidityThresh
+        commStatus  => { oid => '.1.3.6.1.4.1.318.1.1.10.5.1.1.1.11', map => $map_comm_status3 }, # wirelessSensorStatusCommStatus
+        highCrit    => { oid => '.1.3.6.1.4.1.318.1.1.10.5.1.1.1.14' }, # wirelessSensorStatusMaxHumidityThresh
+        lowCrit     => { oid => '.1.3.6.1.4.1.318.1.1.10.5.1.1.1.15' }  # wirelessSensorStatusMinHumidityThresh
+    };
+
+    my $snmp_result = $self->{snmp_wireless_sensors};
+    if ($self->{checked_wireless_sensors} == 0) {
+        $self->{snmp_wireless_sensors} = $self->{snmp}->get_table(oid => $oid_wirelessSensorStatusTable, end => $oid_wirelessSensorStatusMinHumidityThresh);
+        $self->{checked_wireless_sensors} = 1;
+    }
+
+    foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{snmp_wireless_sensors}})) {
+        next if ($oid !~ /^$mapping->{commStatus}->{oid}\.(\d+)$/);
+
+        my $instance = $1;
+        my $result = $self->{snmp}->map_instance(
+            mapping => $mapping,
+            results => $self->{snmp_wireless_sensors},
+            instance => $instance
+        );
+
+        $instance = 'wireless.' . $instance;
+
+        next if ($self->check_filter(section => 'humidity', instance => $instance));
+        $self->{components}->{humidity}->{total}++;
+
+        my $name = $result->{name};
+        $self->{output}->output_add(
+            long_msg => sprintf(
+                "humidity '%s' is %s %% [instance: %s] [comm: %s]",
+                $name,
+                $result->{humidity},
+                $instance, 
+                $result->{commStatus}
+            )
+        );
+
+        my $exit = $self->get_severity(label => 'default', section => 'humdity.comm', value => $result->{commStatus});
+        if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
+            $self->{output}->output_add(
+                severity => $exit,
+                short_msg => sprintf(
+                    "Humidity '%s' communication status is %s",
+                    $name,
+                    $result->{commStatus}
+                )
+            );
+        }
+
+        next if ($result->{humidity} == -1);
+
+        my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'humidity', instance => $instance, value => $result->{humidity});
+        if ($checked == 0) {
+            my $warn_th = ($result->{lowWarn}) . ':' . ($result->{highCrit});
+            my $crit_th = ($result->{lowCrit}) . ':' . ($result->{highCrit});
+            $self->{perfdata}->threshold_validate(label => 'warning-humidity-instance-' . $instance, value => $warn_th);
+            $self->{perfdata}->threshold_validate(label => 'critical-humidity-instance-' . $instance, value => $crit_th);
+            $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-humidity-instance-' . $instance);
+            $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-humidity-instance-' . $instance);
+            $exit = $self->{perfdata}->threshold_check(
+                value => $result->{humidity},
+                threshold => [
+                    { label => 'critical-humidity-instance-' . $instance, exit_litteral => 'critical' },
+                    { label => 'warning-humidity-instance-' . $instance, exit_litteral => 'warning' }
+                ]
+            );
+        }
+
+        if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) {
+            $self->{output}->output_add(
+                severity => $exit2,
+                short_msg => sprintf(
+                    "Humidity '%s' is %s %%",
+                    $name,
+                    $result->{humidity}
+                )
+            );
+        }
+
+        $self->{output}->perfdata_add(
+            nlabel => 'hardware.sensor.humidity.percentage',
+            unit => '%',
+            instances => $name,
+            value => $result->{humidity},
+            warning => $warn,
+            critical => $crit,
+            min => 0,
+            max => 100
+        );
+    }
+}
+
+sub check {
+    my ($self) = @_;
+
+    $self->{output}->output_add(long_msg => "Checking humidities");
+    $self->{components}->{humidity} = { name => 'humidity', total => 0, skip => 0 };
+    return if ($self->check_filter(section => 'humidity'));
+
+    check_module_humidity($self);
+    check_wireless_humidity($self);
+}
+
+1;
diff --git a/centreon-plugins/hardware/sensors/apc/snmp/mode/components/resources.pm b/centreon-plugins/hardware/sensors/apc/snmp/mode/components/resources.pm
new file mode 100644
index 000000000..e232abea0
--- /dev/null
+++ b/centreon-plugins/hardware/sensors/apc/snmp/mode/components/resources.pm
@@ -0,0 +1,64 @@
+#
+# Copyright 2022 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 hardware::sensors::apc::snmp::mode::components::resources;
+
+use strict;
+use warnings;
+use Exporter;
+
+our $map_alarm_status;
+our $map_comm_status;
+our $map_comm_status2;
+our $map_comm_status3;
+our $map_fluid_state;
+
+our @ISA = qw(Exporter);
+our @EXPORT_OK = qw($map_alarm_status $map_fluid_state $map_comm_status $map_comm_status2 $map_comm_status3);
+
+$map_alarm_status = {
+    1 => 'normal',
+    2 => 'warning',
+    3 => 'critical'
+};
+
+$map_comm_status = {
+    1 => 'notInstalled',
+    2 => 'ok',
+    3 => 'lost'
+};
+
+$map_comm_status2 = {
+    1 => 'ok',
+    2 => 'lost'
+};
+
+$map_comm_status3 = {
+    0 => 'inactive',
+    1 => 'active'
+};
+
+$map_fluid_state = {
+    1 => 'fluidDetected',
+    2 => 'noFuild',
+    3 => 'unknown'
+};
+
+1;
diff --git a/centreon-plugins/hardware/sensors/apc/snmp/mode/components/temperature.pm b/centreon-plugins/hardware/sensors/apc/snmp/mode/components/temperature.pm
new file mode 100644
index 000000000..b347296a0
--- /dev/null
+++ b/centreon-plugins/hardware/sensors/apc/snmp/mode/components/temperature.pm
@@ -0,0 +1,235 @@
+#
+# Copyright 2022 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 hardware::sensors::apc::snmp::mode::components::temperature;
+
+use strict;
+use warnings;
+use hardware::sensors::apc::snmp::mode::components::resources qw($map_alarm_status $map_comm_status $map_comm_status3);
+
+sub load {}
+
+sub check_module_temp {
+    my ($self) = @_;
+
+    my $oid_memSensorsStatusTable = '.1.3.6.1.4.1.318.1.1.10.4.2.3';
+    my $mapping = {
+        name        => { oid => '.1.3.6.1.4.1.318.1.1.10.4.2.3.1.3' }, # memSensorsStatusSensorName
+        temp        => { oid => '.1.3.6.1.4.1.318.1.1.10.4.2.3.1.5' }, # memSensorsTemperature
+        commStatus  => { oid => '.1.3.6.1.4.1.318.1.1.10.4.2.3.1.7', map => $map_comm_status }, # memSensorsCommStatus
+        alarmStatus => { oid => '.1.3.6.1.4.1.318.1.1.10.4.2.3.1.8', map => $map_alarm_status } # memSensorsAlarmStatus
+    };
+
+    my $snmp_result = $self->{snmp_module_sensors};
+    if ($self->{checked_module_sensors} == 0) {
+        $self->{snmp_module_sensors} = $self->{snmp}->get_table(oid => $oid_memSensorsStatusTable);
+        $self->{checked_module_sensors} = 1;
+    }
+
+    foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{snmp_module_sensors}})) {
+        next if ($oid !~ /^$mapping->{alarmStatus}->{oid}\.(\d+)\.(\d+)$/);
+
+        my $module_name = $self->{modules_name}->{$1};
+        my $instance = $1 . '.' . $2;
+        my $result = $self->{snmp}->map_instance(
+            mapping => $mapping,
+            results => $self->{snmp_module_sensors},
+            instance => $instance
+        );
+
+        $instance = 'module.' . $instance;
+
+        next if ($self->check_filter(section => 'temperature', instance => $instance));
+        $self->{components}->{temperature}->{total}++;
+
+        my $name = $module_name . ':' . $result->{name};
+        $self->{output}->output_add(
+            long_msg => sprintf(
+                "temperature '%s' alarm status is %s [instance: %s] [value: %s] [comm: %s]",
+                $name,
+                $result->{alarmStatus},
+                $instance, 
+                $result->{temp},
+                $result->{commStatus}
+            )
+        );
+
+        my $exit = $self->get_severity(label => 'default', section => 'temperature.alarm', value => $result->{alarmStatus});
+        if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
+            $self->{output}->output_add(
+                severity => $exit,
+                short_msg => sprintf(
+                    "Temperature '%s' alarm status is %s",
+                    $name,
+                    $result->{alarmStatus}
+                )
+            );
+        }
+
+        $exit = $self->get_severity(label => 'default', section => 'temperature.comm', value => $result->{commStatus});
+        if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
+            $self->{output}->output_add(
+                severity => $exit,
+                short_msg => sprintf(
+                    "Temperature '%s' communication status is %s",
+                    $name,
+                    $result->{commStatus}
+                )
+            );
+        }
+
+        my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $result->{temp});
+        if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) {
+            $self->{output}->output_add(
+                severity => $exit2,
+                short_msg => sprintf(
+                    "Temperature '%s' is %s %s",
+                    $name,
+                    $result->{temp},
+                    $self->{temp_unit}
+                )
+            );
+        }
+
+        $self->{output}->perfdata_add(
+            nlabel => 'hardware.sensor.temperature.' . ($self->{temp_unit} eq 'C' ? 'celsius' : 'fahrenheit'),
+            unit => $self->{temp_unit},
+            instances => $name,
+            value => $result->{temp},
+            warning => $warn,
+            critical => $crit
+        );
+    }
+}
+
+sub check_wireless_temp {
+    my ($self) = @_;
+
+    my $oid_wirelessSensorStatusTable = '.1.3.6.1.4.1.318.1.1.10.5.1.1';
+    my $oid_wirelessSensorStatusMinHumidityThresh = '.1.3.6.1.4.1.318.1.1.10.5.1.1.1.15';
+    my $mapping = {
+        name        => { oid => '.1.3.6.1.4.1.318.1.1.10.5.1.1.1.3' }, # wirelessSensorStatusName
+        temp        => { oid => '.1.3.6.1.4.1.318.1.1.10.5.1.1.1.5' }, # wirelessSensorStatusTemperature
+        highWarn    => { oid => '.1.3.6.1.4.1.318.1.1.10.5.1.1.1.6' }, # wirelessSensorStatusHighTempThresh
+        lowWarn     => { oid => '.1.3.6.1.4.1.318.1.1.10.5.1.1.1.7' }, # wirelessSensorStatusLowTempThresh
+        commStatus  => { oid => '.1.3.6.1.4.1.318.1.1.10.5.1.1.1.11', map => $map_comm_status3 }, # wirelessSensorStatusCommStatus
+        highCrit    => { oid => '.1.3.6.1.4.1.318.1.1.10.5.1.1.1.12' }, # wirelessSensorStatusHighTempThresh
+        lowCrit     => { oid => '.1.3.6.1.4.1.318.1.1.10.5.1.1.1.13' }  # wirelessSensorStatusLowTempThresh
+    };
+
+    my $snmp_result = $self->{snmp_wireless_sensors};
+    if ($self->{checked_wireless_sensors} == 0) {
+        $self->{snmp_wireless_sensors} = $self->{snmp}->get_table(oid => $oid_wirelessSensorStatusTable, end => $oid_wirelessSensorStatusMinHumidityThresh);
+        $self->{checked_wireless_sensors} = 1;
+    }
+
+    foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{snmp_wireless_sensors}})) {
+        next if ($oid !~ /^$mapping->{commStatus}->{oid}\.(\d+)$/);
+
+        my $instance = $1;
+        my $result = $self->{snmp}->map_instance(
+            mapping => $mapping,
+            results => $self->{snmp_wireless_sensors},
+            instance => $instance
+        );
+
+        $instance = 'wireless.' . $instance;
+
+        next if ($self->check_filter(section => 'temperature', instance => $instance));
+        $self->{components}->{temperature}->{total}++;
+
+        my $name = $result->{name};
+        $result->{temp} *= 0.1;
+
+        $self->{output}->output_add(
+            long_msg => sprintf(
+                "temperature '%s' is %s %s [instance: %s] [comm: %s]",
+                $name,
+                $result->{temp},
+                $self->{temp_unit},
+                $instance, 
+                $result->{commStatus}
+            )
+        );
+
+        my $exit = $self->get_severity(label => 'default', section => 'temperature.comm', value => $result->{commStatus});
+        if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
+            $self->{output}->output_add(
+                severity => $exit,
+                short_msg => sprintf(
+                    "Temperature '%s' communication status is %s",
+                    $name,
+                    $result->{commStatus}
+                )
+            );
+        }
+
+        my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $result->{temp});
+        if ($checked == 0) {
+            my $warn_th = ($result->{lowWarn} * 0.1) . ':' . ($result->{highCrit} * 0.1);
+            my $crit_th = ($result->{lowCrit} * 0.1) . ':' . ($result->{highCrit} * 0.1);
+            $self->{perfdata}->threshold_validate(label => 'warning-temperature-instance-' . $instance, value => $warn_th);
+            $self->{perfdata}->threshold_validate(label => 'critical-temperature-instance-' . $instance, value => $crit_th);
+            $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-temperature-instance-' . $instance);
+            $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-temperature-instance-' . $instance);
+            $exit = $self->{perfdata}->threshold_check(
+                value => $result->{temp},
+                threshold => [
+                    { label => 'critical-temperature-instance-' . $instance, exit_litteral => 'critical' },
+                    { label => 'warning-temperature-instance-' . $instance, exit_litteral => 'warning' }
+                ]
+            );
+        }
+
+        if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) {
+            $self->{output}->output_add(
+                severity => $exit2,
+                short_msg => sprintf(
+                    "Temperature '%s' is %s %s",
+                    $name,
+                    $result->{temp},
+                    $self->{temp_unit}
+                )
+            );
+        }
+
+        $self->{output}->perfdata_add(
+            nlabel => 'hardware.sensor.temperature.' . ($self->{temp_unit} eq 'C' ? 'celsius' : 'fahrenheit'),
+            unit => $self->{temp_unit},
+            instances => $name,
+            value => $result->{temp},
+            warning => $warn,
+            critical => $crit
+        );
+    }
+}
+
+sub check {
+    my ($self) = @_;
+
+    $self->{output}->output_add(long_msg => "Checking temperatures");
+    $self->{components}->{temperature} = { name => 'temperatures', total => 0, skip => 0 };
+    return if ($self->check_filter(section => 'temperature'));
+
+    check_module_temp($self);
+    check_wireless_temp($self);
+}
+
+1;
diff --git a/centreon-plugins/hardware/sensors/apc/snmp/mode/sensors.pm b/centreon-plugins/hardware/sensors/apc/snmp/mode/sensors.pm
new file mode 100644
index 000000000..1768ff145
--- /dev/null
+++ b/centreon-plugins/hardware/sensors/apc/snmp/mode/sensors.pm
@@ -0,0 +1,127 @@
+#
+# Copyright 2022 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 hardware::sensors::apc::snmp::mode::sensors;
+
+use base qw(centreon::plugins::templates::hardware);
+
+use strict;
+use warnings;
+
+sub set_system {
+    my ($self, %options) = @_;
+
+    $self->{regexp_threshold_numeric_check_section_option} = '^(?:temperature|humidity)$';
+
+    $self->{cb_hook2} = 'snmp_execute';
+
+    $self->{thresholds} = {
+        default => [        
+            ['normal', 'OK'],         # alarmStatus
+            ['warning', 'WARNING'],   # alarmStatus
+            ['critical', 'CRITICAL'], # alarmStatus
+            ['ok', 'OK'],             # commStatus
+            ['notInstalled', 'OK'],   # commStatus
+            ['lost', 'WARNING'],      # commStatus
+            ['^active', 'OK'],        # commStatus
+            ['inactive', 'OK']        # commStatus
+        ]
+    };
+
+    $self->{components_path} = 'hardware::sensors::apc::snmp::mode::components';
+    $self->{components_module} = [
+        'temperature', 'humidity', 'fluid'
+    ];
+}
+
+sub snmp_execute {
+    my ($self, %options) = @_;
+
+    $self->{snmp} = $options{snmp};
+    $self->{checked_module_sensors} = 0;
+    $self->{checked_wireless_sensors} = 0;
+
+    my $oid_module_name = '.1.3.6.1.4.1.318.1.1.10.4.1.2.1.2';
+    my $snmp_result = $self->{snmp}->get_table(oid => $oid_module_name);
+    $self->{modules_name} = {};
+    foreach (keys %$snmp_result) {
+        /$oid_module_name\.(.*)$/;
+        $self->{modules_name}->{$1} = $snmp_result->{$_};
+    }
+
+    my $oid_emsStatusSysTempUnits = '.1.3.6.1.4.1.318.1.1.10.3.12.11.0';
+    $snmp_result = $self->{snmp}->get_leef(oids => [$oid_emsStatusSysTempUnits]);
+    $self->{temp_unit} = $snmp_result->{$oid_emsStatusSysTempUnits} == 1 ? 'C' : 'F';
+}
+
+sub new {
+    my ($class, %options) = @_;
+    my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_absent => 1, force_new_perfdata => 1);
+    bless $self, $class;
+
+    $options{options}->add_options(arguments => {});
+
+    return $self;
+}
+
+1;
+
+__END__
+
+=head1 MODE
+
+Check sensors.
+
+=over 8
+
+=item B<--component>
+
+Which component to check (Default: '.*').
+Can be: 'temperature', 'humidity', 'fluid'.
+
+=item B<--filter>
+
+Exclude some parts (comma seperated list) (Example: --filter=temperature --filter=humidity)
+Can also exclude specific instance: --filter=temperature,1
+
+=item B<--no-component>
+
+Return an error if no compenents are checked.
+If total (with skipped) is 0. (Default: 'critical' returns).
+
+=item B<--threshold-overload>
+
+Set to overload default threshold values (syntax: section,[instance,]status,regexp)
+It used before default thresholds (order stays).
+Example: --threshold-overload='temperature,CRITICAL,^(?!(warning)$)'
+
+=item B<--warning>
+
+Set warning threshold for 'temperature', 'humidity' (syntax: type,regexp,threshold)
+Example: --warning='temperature,.*,30'
+
+=item B<--critical>
+
+Set critical threshold for 'temperature', 'humidity' (syntax: type,regexp,threshold)
+Example: --warning='temperature,.*,50'
+
+=back
+
+=cut
diff --git a/centreon-plugins/hardware/sensors/apc/snmp/plugin.pm b/centreon-plugins/hardware/sensors/apc/snmp/plugin.pm
new file mode 100644
index 000000000..29aabe028
--- /dev/null
+++ b/centreon-plugins/hardware/sensors/apc/snmp/plugin.pm
@@ -0,0 +1,47 @@
+#
+# Copyright 2022 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 hardware::sensors::apc::snmp::plugin;
+
+use strict;
+use warnings;
+use base qw(centreon::plugins::script_snmp);
+
+sub new {
+    my ($class, %options) = @_;
+    my $self = $class->SUPER::new(package => __PACKAGE__, %options);
+    bless $self, $class;
+
+    $self->{modes} = {
+        'sensors' => 'hardware::sensors::apc::snmp::mode::sensors'
+    };
+
+    return $self;
+}
+
+1;
+
+__END__
+
+=head1 PLUGIN DESCRIPTION
+
+Check APC sensors (also netboz250) in SNMP.
+
+=cut