banshee is under active development: collectors will keep changing, and a version you publish will likely need adjustments. For stable use, wait for version 1.0.0.

Network

banshee/network-collection/network/mikrotik/snmp/

health

The hardware health of a MikroTik RouterOS or SwitchOS device by SNMP: temperatures, fans, voltages, power, power supplies.

  • network
  • snmp
  • mikrotik
  • routeros
  • swos
  • temperature
  • fan
  • power-supply

by banshee1 installation2 versions

v2Latest

Published on October 28, 2026. One naming convention across collections; documentation completed.

Keen 1.0.0 · 118 lines
// The hardware health of a MikroTik device, by SNMP (MIKROTIK-MIB, mtxrHealth): temperatures, fan speeds,
// voltages, currents, power, and the state of the power supplies. RouterOS 7, and the late versions of
// RouterOS 6, serve mtxrGaugeTable, one row per sensor named by the device ("cpu-temperature", "fan1-speed",
// "psu1-state"); an older RouterOS, and SwitchOS, serve the fixed objects of mtxrHealth instead, which the
// collector reads when the table is empty. A device that serves neither, such as a virtual router (CHR),
// stops the collector, rather than stay green on nothing.
need('protocol:snmp');

per('sensor', 'Sensors');
output('temperature', 'number', array('label' => 'Temperature', 'unit' => '°C', 'per' => 'sensor'));
output('fan-speed', 'number', array('label' => 'Fan speed', 'unit' => 'rpm', 'per' => 'sensor'));
output('voltage', 'number', array('label' => 'Voltage', 'unit' => 'V', 'per' => 'sensor'));
output('current', 'number', array('label' => 'Current', 'unit' => 'A', 'per' => 'sensor'));
output('power', 'number', array('label' => 'Power', 'unit' => 'W', 'per' => 'sensor'));
output('status', 'text', array('label' => 'State', 'per' => 'sensor'));

watch.above('hot', 'High temperature', 'temperature', array('warning' => 70, 'critical' => 85, 'for' => '3 runs'));
watch.state('failed', 'Power supply failed', 'status', array('critical' => array('fail')));
// Not checked by default: many MikroTik devices stop their fans while they are cool.
watch.below('fan-stopped', 'Fan stopped', 'fan-speed', array('critical' => 1, 'for' => '2 runs', 'enabled' => false));
watch.below('voltage-low', 'Low voltage', 'voltage', array(
    'help'    => 'Raises below the voltage set on the probe: the input voltage of a device depends on its power source.',
    'enabled' => false,
));
watch.missing('missing', 'Sensor missing', 'status', array('enabled' => false));

// Returns one measure under the output of its kind, and 1, the measure counted.
function report($kind, $measure, $name) {
    if ($kind == 'temperature') {
        value('temperature', $measure, $name);
    } elseif ($kind == 'fan-speed') {
        value('fan-speed', $measure, $name);
    } elseif ($kind == 'voltage') {
        value('voltage', $measure, $name);
    } elseif ($kind == 'current') {
        value('current', $measure, $name);
    } elseif ($kind == 'power') {
        value('power', $measure, $name);
    } else {
        value('status', $measure, $name);
    }
    return 1;
}

// mtxrGaugeTable, by mtxrGaugeIndex: mtxrGaugeName, mtxrGaugeValue and mtxrGaugeUnit.
$gauges = snmp.table(array(
    'name'  => '1.3.6.1.4.1.14988.1.1.3.100.1.2',
    'value' => '1.3.6.1.4.1.14988.1.1.3.100.1.3',
    'unit'  => '1.3.6.1.4.1.14988.1.1.3.100.1.4',
));

$read = 0;
// mtxrGaugeUnit: celsius (1), rpm (2), dV (3), dA (4), dW (5), status (6). A status reads 0 when it is ok
// and 1 when it fails, as RouterOS shows "ok" and "fail".
$kinds = array(1 => 'temperature', 2 => 'fan-speed', 3 => 'voltage', 4 => 'current', 5 => 'power', 6 => 'status');
foreach ($gauges as $index => $row) {
    if (!list.has($row, 'name') || !list.has($row, 'value') || !list.has($kinds, list.get($row, 'unit', 0))) {
        continue;
    }
    $kind = $kinds[$row['unit']];
    $measure = $row['value'];
    if ($row['unit'] >= 3 && $row['unit'] <= 5) {
        $measure = number.round($measure / 10, 1);
    }
    if ($kind == 'status') {
        $measure = 'state ' . $measure;
        if ($row['value'] == 0) {
            $measure = 'ok';
        } elseif ($row['value'] == 1) {
            $measure = 'fail';
        }
    }
    $read = $read + report($kind, $measure, $row['name']);
}

// The fixed objects of mtxrHealth, read when the device serves no gauge. Each one: its name, its kind, and
// what its value is divided by. Voltage, Temperature and Power are in tenths; mtxrHlCurrent in mA;
// mtxrHlPowerSupplyState and mtxrHlBackupPowerSupplyState are true (1) when the supply is ok.
if ($read == 0) {
    $health = snmp.walk('1.3.6.1.4.1.14988.1.1.3');
    $objects = array(
        '1'  => array('name' => 'core-voltage', 'kind' => 'voltage', 'divide' => 10),
        '2'  => array('name' => '3.3v-voltage', 'kind' => 'voltage', 'divide' => 10),
        '3'  => array('name' => '5v-voltage', 'kind' => 'voltage', 'divide' => 10),
        '4'  => array('name' => '12v-voltage', 'kind' => 'voltage', 'divide' => 10),
        '5'  => array('name' => 'sensor-temperature', 'kind' => 'temperature', 'divide' => 10),
        '6'  => array('name' => 'cpu-temperature', 'kind' => 'temperature', 'divide' => 10),
        '7'  => array('name' => 'board-temperature', 'kind' => 'temperature', 'divide' => 10),
        '8'  => array('name' => 'voltage', 'kind' => 'voltage', 'divide' => 10),
        '10' => array('name' => 'temperature', 'kind' => 'temperature', 'divide' => 10),
        '11' => array('name' => 'processor-temperature', 'kind' => 'temperature', 'divide' => 10),
        '12' => array('name' => 'power-consumption', 'kind' => 'power', 'divide' => 10),
        '13' => array('name' => 'current', 'kind' => 'current', 'divide' => 1000),
        '15' => array('name' => 'psu-state', 'kind' => 'status', 'divide' => 1),
        '16' => array('name' => 'backup-psu-state', 'kind' => 'status', 'divide' => 1),
        '17' => array('name' => 'fan1-speed', 'kind' => 'fan-speed', 'divide' => 1),
        '18' => array('name' => 'fan2-speed', 'kind' => 'fan-speed', 'divide' => 1),
    );
    foreach ($objects as $number => $object) {
        $raw = list.get($health, $number . '.0', '');
        if ($raw == '') {
            continue;
        }
        $measure = number.round($raw / $object['divide'], 1);
        if ($object['kind'] == 'status') {
            $measure = 'fail';
            if ($raw == 1) {
                $measure = 'ok';
            }
        }
        $read = $read + report($object['kind'], $measure, $object['name']);
    }
}

if ($read == 0) {
    fail('misconfigured', 'The device serves no health value (mtxrHealth, MIKROTIK-MIB)',
        'A device without sensors, such as a virtual router (CHR), or a view that does not grant MIKROTIK-MIB to the poller.');
}