Профессиональное сетевое оборудование, такое как роутеры Mikrotik, предоставляет огромное количество данных о своём состоянии: от температуры процессора и скорости вентиляторов до трафика на каждом из десятков портов. Но как собрать всю эту информацию в одном месте и превратить её в наглядные графики для анализа?
В этой статье мы создадим комплексную систему мониторинга для роутера Mikrotik с помощью протокола SNMP, а все собранные данные будем отправлять в VizIoT для построения информативной панели. Вы сможете в реальном времени отслеживать состояние оборудования, нагрузку на сеть и быстро выявлять проблемы.
Прежде чем мы начнём, взгляните, какую мощную и наглядную панель мониторинга мы создадим. Она позволит отслеживать всё: от общего времени работы и статуса блоков питания до детальной загрузки каждого SFP-порта.
Заинтересовались? Давайте настроим такую систему. Это проще, чем кажется.
Протокол SNMP (Simple Network Management Protocol) — это стандартный способ для сетевых устройств предоставлять информацию о своём состоянии.
public. Это имя сообщества, которое работает как пароль. Вы можете оставить его или изменить, но убедитесь, что оно совпадает с настройками в нашем скрипте.Теперь ваш роутер готов отдавать данные по SNMP.
На компьютере, который будет собирать данные, установим всё необходимое.
Подробная документация: https://nodejs.org
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
\. "$HOME/.nvm/nvm.sh"
nvm install 24
node -v
npm -v
mkdir mikrotik-monitor
cd mikrotik-monitor
npm init -y
npm install net-snmp big-integer viziot-mqtt-client-nodejs
Создайте файл index.js:
nano index.js
Вставьте в него следующий код. Не забудьте указать ваши данные в секции CONFIG.
const snmp = require("net-snmp");
const bigInt = require("big-integer");
const viziotMQTT = require("viziot-mqtt-client-nodejs");
// Конфигурация
const CONFIG = {
keyDevice: "ВАШ_КЛЮЧ_УСТРОЙСТВА", // Ключ устройства VizIoT
passDevice: "ВАШ_ПАРОЛЬ_УСТРОЙСТВА", // Пароль устройства VizIoT
intervalSendData: 30000, // Интервал опроса в миллисекундах (30 секунд)
ipRouter: "192.168.0.25", // IP-адрес вашего роутера Mikrotik
snmpCommunity: "public", // Имя SNMP-сообщества (должно совпадать с настройками роутера)
};
// Конвертеры значений
const hexToBigInt = (value) => +bigInt(`0x${value.toString('hex')}`).toString(10)
const divideBy10 = (value) => value / 10
const divideBy100ToDay = (value) => value / 100 / 60 / 60 / 24
const identity = (value) => value
// Генератор OID для rx и tx портов
const generatePortOIDs = () => {
const oids = {}
const rxBase = '1.3.6.1.4.1.14988.1.1.14.1.1.31'
const txBase = '1.3.6.1.4.1.14988.1.1.14.1.1.61'
// SFPP1 порт
oids[`${rxBase}.1`] = { key: 'rx_sfpp1', convert: hexToBigInt }
oids[`${txBase}.1`] = { key: 'tx_sfpp1', convert: hexToBigInt }
// SFP порты 1-12
for (let i = 1; i <= 12; i++) {
oids[`${rxBase}.${i + 1}`] = { key: `rx_sfp${i}`, convert: hexToBigInt }
oids[`${txBase}.${i + 1}`] = { key: `tx_sfp${i}`, convert: hexToBigInt }
}
return oids
}
// Генератор OID для загрузки CPU
const generateProcessorLoadOIDs = () => {
const oids = {}
const base = '1.3.6.1.2.1.25.3.3.1.2.'
// 16-ти ядерный процессор
for (let i = 1; i <= 16; i++) {
oids[`${base}.${i}`] = { key: `cpu${i}`, convert: identity }
}
return oids
}
// SNMP OID конфигурация
const SNMP_OIDS = {
'1.3.6.1.2.1.1.3.0': { key: 'uptime', convert: divideBy100ToDay },
...generatePortOIDs(),
'1.3.6.1.4.1.14988.1.1.3.11.0': { key: 'processorTemp', convert: divideBy10 },
'1.3.6.1.4.1.14988.1.1.3.15.0': { key: 'power1State', convert: identity },
'1.3.6.1.4.1.14988.1.1.3.16.0': { key: 'power2State', convert: identity },
'1.3.6.1.4.1.14988.1.1.3.17.0': { key: 'fan1RPM', convert: identity },
'1.3.6.1.4.1.14988.1.1.3.18.0': { key: 'fan2RPM', convert: identity },
...generateProcessorLoadOIDs(),
}
// Класс для работы с SNMP данными
class SNMPMonitor {
constructor() {
this.prevResult = null
this.mqttClient = new viziotMQTT(CONFIG.keyDevice, CONFIG.passDevice)
this.intervalId = null
}
start() {
this.mqttClient.connect(() => {
console.log(new Date(), 'MQTT подключен')
this.startPolling()
})
}
startPolling() {
if (this.intervalId) {
clearInterval(this.intervalId)
}
this.intervalId = setInterval(() => this.poll(), CONFIG.intervalSendData)
}
async poll() {
try {
const result = await this.getSNMPData()
if (!result) {
console.log(new Date(), 'SNMP результат пустой')
return
}
if (!this.prevResult) {
this.prevResult = result
console.log(new Date(), 'Получен первый SNMP результат')
return
}
const packet = this.buildPacket(result)
this.prevResult = result
// console.log(packet)
this.mqttClient.sendDataToVizIoT(packet, (err) => {
if (!err) console.log(new Date(), 'Пакет отправлен')
})
} catch (error) {
console.error(new Date(), 'Ошибка опроса:', error)
}
}
getSNMPData() {
return new Promise((resolve) => {
const session = snmp.createSession(CONFIG.ipRouter, CONFIG.snmpCommunity)
const oids = Object.keys(SNMP_OIDS)
session.get(oids, (error, varbinds) => {
session.close()
if (error) {
console.error(new Date(), 'SNMP varbinds:', varbinds)
console.error(new Date(), 'SNMP ошибка:', error)
resolve(null)
return
}
const result = { timeGet: Date.now() }
varbinds.forEach((varbind) => {
if (snmp.isVarbindError(varbind)) {
console.error(new Date(), snmp.varbindError(varbind))
return
}
const config = SNMP_OIDS[varbind.oid]
if (config) {
result[config.key] = config.convert(varbind.value)
}
})
resolve(result)
})
})
}
// Вычисление статистики по загрузке CPU
calculateCPUStats(current) {
const cpuLoads = []
// Собираем значения загрузки всех ядер
for (let i = 1; i <= 16; i++) {
const cpuKey = `cpu${i}`
if (current[cpuKey] !== undefined) {
cpuLoads.push(current[cpuKey])
}
}
if (cpuLoads.length === 0) {
return { avg: 0, min: 0, max: 0 }
}
// Вычисляем среднее, минимум и максимум
const sum = cpuLoads.reduce((acc, val) => acc + val, 0)
const avg = Math.round((sum / cpuLoads.length) * 100) / 100
const min = Math.min(...cpuLoads)
const max = Math.max(...cpuLoads)
return { avg, min, max }
}
buildPacket(current) {
const elapsedSec = Math.round((current.timeGet - this.prevResult.timeGet) / 1000)
// Вычисляем статистику CPU
const cpuStats = this.calculateCPUStats(current)
const packet = {
date: Math.floor(Date.now() / 1000),
uptime: current.uptime,
processorTemp: current.processorTemp,
cpuAvg: cpuStats.avg, // Средняя загрузка CPU
cpuMin: cpuStats.min, // Минимальная загрузка по ядрам
cpuMax: cpuStats.max, // Максимальная загрузка по ядрам
power1State: current.power1State,
power2State: current.power2State,
fan1RPM: current.fan1RPM,
fan2RPM: current.fan2RPM,
aggRxMb: 0,
aggTxMb: 0,
}
// Расчет скоростей для всех портов
const ports = ['sfpp1', ...Array.from({ length: 12 }, (_, i) => `sfp${i + 1}`)]
ports.forEach((port) => {
const rxKey = `rx_${port}`
const txKey = `tx_${port}`
if (current[rxKey] !== undefined && this.prevResult[rxKey] !== undefined) {
const rxMb = this.calcBandwidth(current[rxKey], this.prevResult[rxKey], elapsedSec)
const txMb = this.calcBandwidth(current[txKey], this.prevResult[txKey], elapsedSec)
const portName = port.charAt(0).toUpperCase() + port.slice(1)
packet[`rx${portName}Mb`] = rxMb
packet[`tx${portName}Mb`] = txMb
packet.aggRxMb += rxMb
packet.aggTxMb += txMb
}
})
return packet
}
calcBandwidth(current, previous, seconds) {
return ((current - previous) / seconds / 1024 / 1024) * 8
}
stop() {
if (this.intervalId) {
clearInterval(this.intervalId)
this.intervalId = null
}
}
}
// Запуск мониторинга
const monitor = new SNMPMonitor()
monitor.start()
// Обработка завершения процесса
process.on('SIGINT', () => {
console.log('\nОстановка мониторинга...')
monitor.stop()
process.exit(0)
})
Чтобы скрипт работал 24/7, используем менеджер процессов PM2.
Установите PM2 глобально:
npm install pm2 -g
Запустите скрипт через PM2:
pm2 start index.js --name "mikrotik-monitor"
Настройте автозапуск PM2 при старте системы:
pm2 startup
Скопируйте и выполните команду, которую выдаст PM2.
Сохраните текущий список процессов:
pm2 save
Теперь ваш скрипт-сборщик будет надёжно работать в фоновом режиме.
Самая интересная часть! Данные поступают, и теперь мы можем их визуализировать.
Создайте новую панель с именем "Mikrotik Router".
Начните добавлять виджеты. VizIoT автоматически создаст параметры при получении первых данных. Вот несколько идей для виджетов:
uptime, power1State, power2State.processorTemp или fan1RPM.aggRxMb (входящий) и aggTxMb (исходящий).processorTemp, fan1RPM, fan2RPM.rx...Mb и tx...Mb параметры.Экспериментируйте с типами виджетов и компоновкой, чтобы создать панель, которая будет идеально соответствовать вашим задачам.
Вы создали мощную и гибкую систему мониторинга для вашего роутера Mikrotik. Теперь вы всегда будете в курсе состояния вашего сетевого оборудования и сможете оперативно реагировать на любые аномалии в трафике или работе устройства.