Hardware
banshee/hardware-collection/hardware/ups/apc/snmp/
status
The battery to replace, defective battery packs, operating state, runtime, load and self-test of an APC UPS by SNMP.
par banshee0 installation1 version
v1Dernière
Publiée le 28 octobre 2026. First version.
// An APC UPS, by SNMP, through its network management card (PowerNet-MIB): what UPS-MIB does not say, the
// battery the UPS asks to replace and the external battery packs it finds defective, and its operating state
// in APC's own words (on line, on battery, smart boost or trim, the kinds of bypass, off); with the runtime,
// charge, temperature, load and last self-test, so that one probe is enough on a card where UPS-MIB is off.
need('protocol:snmp');
output('status', 'text', array('label' => 'Operating state'));
output('replace-battery', 'text', array('label' => 'Battery to replace'));
output('bad-battery-packs', 'number', array('label' => 'Defective battery packs'));
output('runtime', 'number', array('label' => 'Runtime left', 'unit' => 'min'));
output('charge', 'number', array('label' => 'Battery charge', 'unit' => '%'));
output('temperature', 'number', array('label' => 'Internal temperature', 'unit' => '°C'));
output('load', 'number', array('label' => 'Load', 'unit' => '%'));
output('self-test', 'text', array('label' => 'Last self-test'));
watch.state('on-battery', 'On battery, bypass or off', 'status', array(
'warning' => array('on-battery', 'software-bypass', 'switched-bypass', 'static-bypass-standby'),
'critical' => array('off', 'hardware-failure-bypass', 'emergency-static-bypass', 'timed-sleeping', 'sleeping-until-power-return'),
));
watch.state('replace-battery', 'Battery to replace', 'replace-battery', array('warning' => array('yes')));
watch.above('bad-battery-packs', 'Defective battery packs', 'bad-battery-packs', array('warning' => 0));
watch.below('runtime', 'Little runtime left', 'runtime', array('warning' => 15, 'critical' => 5));
watch.below('charge', 'Battery not charged', 'charge', array('warning' => 50, 'critical' => 20, 'for' => '2 runs'));
watch.above('temperature', 'UPS too hot', 'temperature', array('warning' => 40, 'critical' => 50, 'for' => '3 runs'));
watch.above('load', 'Overloaded', 'load', array('warning' => 80, 'critical' => 95, 'for' => '3 runs'));
watch.state('self-test', 'Self-test failed', 'self-test', array('critical' => array('failed')));
// PowerNet-MIB, under upsObjects of APC (1.3.6.1.4.1.318.1.1.1), four small branches; each key is the rest of
// the OID: '1.0' is upsBasicOutputStatus.0 in the first.
$basic_output = snmp.walk('1.3.6.1.4.1.318.1.1.1.4.1');
$advanced_output = snmp.walk('1.3.6.1.4.1.318.1.1.1.4.2');
$battery = snmp.walk('1.3.6.1.4.1.318.1.1.1.2.2');
$test = snmp.walk('1.3.6.1.4.1.318.1.1.1.7.2');
if (!list.has($basic_output, '1.0')) {
fail('misconfigured', 'The agent serves no APC UPS state (upsBasicOutputStatus, PowerNet-MIB)',
'Not an APC UPS, or a view that does not include 1.3.6.1.4.1.318.1.1.1.');
}
// upsBasicOutputStatus, in APC's words.
$states = array(1 => 'unknown', 2 => 'on-line', 3 => 'on-battery', 4 => 'smart-boost', 5 => 'timed-sleeping',
6 => 'software-bypass', 7 => 'off', 8 => 'rebooting', 9 => 'switched-bypass', 10 => 'hardware-failure-bypass',
11 => 'sleeping-until-power-return', 12 => 'smart-trim', 13 => 'eco-mode', 14 => 'hot-standby',
15 => 'on-battery-test', 16 => 'emergency-static-bypass', 17 => 'static-bypass-standby',
18 => 'power-saving-mode', 19 => 'spot-mode', 20 => 'e-conversion', 21 => 'charger-spot-mode',
22 => 'inverter-spot-mode', 23 => 'active-load', 24 => 'battery-discharge-spot-mode',
25 => 'inverter-standby', 26 => 'charger-only', 27 => 'distributed-energy-reserve', 28 => 'self-test');
value('status', list.get($states, $basic_output['1.0'], 'state ' . $basic_output['1.0']));
// upsAdvBatteryReplaceIndicator: noBatteryNeedsReplacing (1), batteryNeedsReplacing (2).
if (list.has($battery, '4.0')) {
$replace = 'no';
if ($battery['4.0'] == 2) {
$replace = 'yes';
}
value('replace-battery', $replace);
}
// upsAdvBatteryNumOfBadBattPacks: the external packs found defective.
if (list.has($battery, '6.0')) {
value('bad-battery-packs', $battery['6.0']);
}
// upsAdvBatteryRunTimeRemaining, in hundredths of a second; 4294967295 when the UPS does not know it.
if (list.has($battery, '3.0') && $battery['3.0'] < 4294967295) {
value('runtime', number.round($battery['3.0'] / 6000, 1));
}
// upsAdvBatteryCapacity, in %.
if (list.has($battery, '1.0')) {
value('charge', $battery['1.0']);
}
// upsAdvBatteryTemperature, the internal temperature in °C; 255 when the UPS does not know it.
if (list.has($battery, '2.0') && $battery['2.0'] < 255) {
value('temperature', $battery['2.0']);
}
// upsAdvOutputLoad, in % of the UPS's capacity.
if (list.has($advanced_output, '3.0')) {
value('load', $advanced_output['3.0']);
}
// upsAdvTestDiagnosticsResults: ok (1), failed (2), invalidTest (3), testInProgress (4).
$results = array(1 => 'ok', 2 => 'failed', 3 => 'invalid-test', 4 => 'in-progress');
if (list.has($test, '3.0')) {
value('self-test', list.get($results, $test['3.0'], 'unknown'));
}