Соответствует ли скорость вашего интернета заявленной в тарифе? Почему Wi-Fi в дальней комнате работает медленнее, чем у роутера? Чтобы получить точные ответы на эти вопросы, обычных веб-сайтов для проверки скорости недостаточно. Нужен профессиональный инструмент — iperf3.
В этом руководстве мы настроим систему автоматического мониторинга, которая будет регулярно измерять "чистую" пропускную способность вашей сети, а результаты отправлять в VizIoT для наглядной визуализации.
Прежде чем мы перейдем к техническим деталям, давайте посмотрим, что у нас получится. Вы сможете создать интерактивную панель, которая в реальном времени будет отображать:
Такая панель позволит вам не просто "измерить скорость", а постоянно контролировать качество вашего сетевого соединения.
iperf3 — это консольная утилита для измерения максимальной пропускной способности сети между двумя точками (клиентом и сервером).
В отличие от веб-сайтов, iperf3 измеряет "чистую" производительность вашего канала, исключая такие факторы, как производительность браузера, загруженность веб-сервера или влияние рекламы на странице. Это "золотой стандарт" для сетевых инженеров, который позволяет:
Наш скрипт будет использовать три ключевых режима для получения полной картины:
Настройка системы состоит из трёх простых шагов: подготовка среды, создание скрипта и его автоматический запуск.
На машине, которая будет выполнять тесты, установим всё необходимое.
Подробная документация: 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
sudo apt update
sudo apt install iperf3 -y
Создайте директорию для проекта:
mkdir viziot_iperf3 && cd viziot_iperf3
Инициализируйте проект и установите зависимости:
npm init -y
npm install viziot-mqtt-client-nodejs
Включите поддержку ES-модулей: Откройте файл package.json и добавьте строку "type": "module",.
Создайте основной файл скрипта:
nano main.js
Вставьте в него следующий код. Не забудьте указать ваши ключ и пароль от устройства VizIoT. В качестве цели для теста мы будем использовать один из общедоступных серверов iperf3.
import VizIoTMQTT from 'viziot-mqtt-client-nodejs'
import { spawn } from 'child_process'
// ===================================
// ========== НАСТРОЙКИ ==============
// ===================================
// 1. Введите ключ и пароль вашего устройства VizIoT
const keyDevice = '________________';
const passDevice = '____________________';
// 2. Установите интервал запуска тестов (сейчас - раз в час)
const intervalTime = 1000 * 60 * 60; // 1 час в миллисекундах
// 3. Настройте список серверов для тестирования.
const servers = [
{
// Пример: Тестирование до публичного сервера в Болгарии
name: 'BG_Sofia',
command: '-c 37.19.203.1',
}
];
// --- Остальная часть кода универсальна и не требует изменений ---
const MAX_RETRIES = 3;
const RETRY_DELAY_MS = 30 * 1000;
const IPERF_TIMEOUT_MS = 60 * 1000;
const objMQTTClient = new VizIoTMQTT(keyDevice, passDevice);
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
function runCommand(command, args, timeoutMs) {
return new Promise((resolve) => {
const child = spawn(command, args, { timeout: timeoutMs });
let stdout = '', stderr = '', timedOut = false;
child.stdout.on('data', (data) => (stdout += data.toString()));
child.stderr.on('data', (data) => (stderr += data.toString()));
child.on('error', (err) => (stderr += `\nНе удалось запустить подпроцесс: ${err.message}`));
child.on('close', (code, signal) => {
if (signal === 'SIGTERM') {
timedOut = true;
stderr += '\nПроцесс был завершен по таймауту.';
}
resolve({ stdout, stderr, code, timedOut });
});
});
}
async function runIperfTest(iperfPath, serverCommand, testMode) {
const testType = testMode.charAt(0).toUpperCase() + testMode.slice(1);
const args = serverCommand.trim().split(' ');
args.push('-J'); // JSON-вывод
if (testMode === 'download') args.push('-R');
else if (testMode === 'bidir') args.push('--bidir');
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
console.log(`[ИНФО] Запускаем тест: ${testType} для ${serverCommand.trim()}. Попытка ${attempt}/${MAX_RETRIES}...`);
const { stdout, stderr, timedOut } = await runCommand(iperfPath, args, IPERF_TIMEOUT_MS);
const errorResult = { upload: -1, download: -1 };
if (timedOut) { console.error(`[ОШИБКА] Тест (${testType}) превысил таймаут.`); return errorResult; }
if (!stdout) { console.error(`[КРИТ] Команда iperf3 не вернула результат. Stderr: ${stderr.trim()}`); return errorResult; }
try {
const result = JSON.parse(stdout);
if (result.error) {
if (result.error.includes('the server is busy')) {
console.warn(`[ПРЕД] Сервер занят. Попытка ${attempt} не удалась.`);
if (attempt < MAX_RETRIES) { await delay(RETRY_DELAY_MS); continue; }
else { console.error(`[ОШИБКА] Сервер занят после ${MAX_RETRIES} попыток.`); return errorResult; }
} else { console.error(`[ОШИБКА] iperf3:`, result.error); return errorResult; }
}
const finalResult = { upload: -1, download: -1 };
const summary = result.end;
if (summary.sum_sent) finalResult.upload = parseFloat((summary.sum_sent.bits_per_second / 1000000).toFixed(2));
if (summary.sum_received) finalResult.download = parseFloat((summary.sum_received.bits_per_second / 1000000).toFixed(2));
console.log(`[УСПЕХ] Результат (${testType}): Отдача: ${finalResult.upload} Мбит/с, Загрузка: ${finalResult.download} Мбит/с`);
return finalResult;
} catch (parseError) { console.error(`[КРИТ] Не удалось разобрать JSON-ответ от iperf3. Ответ:`, stdout); return errorResult; }
}
return { upload: -1, download: -1 };
}
async function getPacketAndSendToServer() {
const results = {};
for (const server of servers) {
console.log(`\n--- Начинаем серию тестов для сервера: ${server.name} ---`);
const uploadResult = await runIperfTest('iperf3', server.command, 'upload');
results[`${server.name}_upload`] = uploadResult.upload;
const downloadResult = await runIperfTest('iperf3', server.command, 'download');
results[`${server.name}_download`] = downloadResult.download;
const bidirResult = await runIperfTest('iperf3', server.command, 'bidir');
results[`${server.name}_bidir_upload`] = bidirResult.upload;
results[`${server.name}_bidir_download`] = bidirResult.download;
}
console.log('\n[УСПЕХ] Все тесты завершены. Итоговый пакет данных:', results);
return results;
}
async function main() {
console.log('[ИНФО] Скрипт запущен. Подключаемся к VizIoT и запускаем первый тест...');
objMQTTClient.connect(() => console.log('[ИНФО] Успешное подключение к VizIoT MQTT.'));
const initialPacket = await getPacketAndSendToServer();
objMQTTClient.sendDataToVizIoT(initialPacket, (err) => {
if (err) console.error(new Date(), 'ОШИБКА отправки начальных данных:', err);
else console.log(new Date(), 'Начальные данные успешно отправлены.');
});
setInterval(async () => {
console.log(`\n[ИНФО] Запускаем плановый тест (интервал: ${intervalTime / 1000} секунд)...`);
const packet = await getPacketAndSendToServer();
objMQTTClient.sendDataToVizIoT(packet, (err) => {
if (err) console.error(new Date(), 'ОШИБКА отправки данных по интервалу:', err);
else console.log(new Date(), 'Данные по интервалу успешно отправлены.');
});
}, intervalTime);
}
main();
Чтобы скрипт работал 24/7, используем менеджер процессов PM2.
npm install pm2 -gpm2 start main.js --name viziot_iperf3pm2 startup (и выполните команду, которую он предложит)pm2 saveПолезные команды PM2:
pm2 list: Показать список запущенных процессов.pm2 logs viziot_iperf3: Смотреть логи.pm2 restart viziot_iperf3: Перезапустить.Теперь, когда у вас есть рабочая система, её легко можно улучшить.
Для максимальной точности лучше тестировать до сервера, который вы контролируете (например, VPS или компьютер в локальной сети).
На серверной машине:
sudo apt update && sudo apt install iperf3 -y
sudo ufw allow 5201/tcp # Открыть порт в брандмауэре
(Согласитесь на запуск iperf3 в режиме сервиса)
На клиентской машине: откройте main.js и добавьте ваш сервер в список.
const servers = [
{
name: 'BG_Sofia', // Публичный сервер
command: '-c 37.19.203.1',
},
{
name: 'LOCAL_SERVER', // Ваш сервер
command: '-c 192.168.0.100', // Укажите IP вашего сервера
}
];
Перезапустите скрипт: pm2 restart viziot_iperf3.
Теперь на вашей панели появятся графики скорости до вашего личного сервера.
После запуска данные начнут поступать в ваше устройство. Зайдите в VizIoT, создайте панель и добавьте виджеты.
..._upload и ..._download.Экспериментируйте, чтобы создать панель, которая будет максимально информативной именно для вас.