
Типичная история при работе с промышленными датчиками выглядит примерно так. Есть RS485- датчик, нашли документацию с картой регистров. Написали Python-скрипт, который раз в 10 секунд опрашивает Modbus, парсит регистры и пишет строчку в CSV. Через неделю скрипт падает — оказывается, что порт занят другим процессом, или systemd не поднял его после перезагрузки, или датчик не ответил три раза подряд и скрипт завис в ожидании. Чиним, причесываем, добавляем watchdog. Потом понимаем, что CSV — плохая идея и надо куда-то писать данные нормально. Этот путь знаком многим в промышленной инженерии, но есть и другой путь.
Суть идеи: Telegraf умеет опрашивать Modbus-устройства напрямую — и сразу писать временные ряды в InfluxDB. Никакого промежуточного кода. Grafana строит графики поверх InfluxDB. Весь стек открытый, работает локально, не требует интернета.
ОГЛАВЛЕНИЕ СТАТЬИ:
Про инструментарий:
Telegraf — это агент сбора метрик от компании InfluxData. Программа-демон, которая работает в фоне на Linux-хосте, по расписанию читает данные из разных источников и пишет их куда скажешь — в данном случае в InfluxDB. Один из плагинов называется inputs.modbus — он умеет опрашивать Modbus-устройства по TCP или RS-485 напрямую.
Grafana — это open-source платформа для аналитики, мониторинга и визуализации данных. Она собирает информацию из разных источников (базы данных, облачные сервисы) и отображает в виде графиков и дашбордов.
Дальше — конкретный пример с датчиком DL-303 (температура, влажность, CO, CO2). В качестве железа — компактный ARM-сборщик NAPI-C на RK3308 с предустановленной ОС NapiLinux, там Telegraf и InfluxDB 2.x есть из коробки. Все команды и конфиги работают на любом Linux-хосте с тем же стеком.
Про работу стека

Рассмотрим комплектность такого решения:
Железо:
Любой Linux-сборщик с портом RS485 и Ethernet. В примере — NAPI-C (RK3308), компактный ARM-компьютер с NapiLinux, где Telegraf и InfluxDB 2.x предустановлены. На любом другом Linux-хосте все команды те же самые.
Датчик с интерфейсом Modbus RTU (RS485) или Modbus TCP.
Программный стек:
Telegraf >= 1.20 (плагин inputs.modbus)
InfluxDB 2.x
Grafana (любая свежая версия)
Для более общего случая, когда ваша ОС не NapiLinux (о ней ниже еще есть раздел) — установите стек вручную или через Docker. Compose-файл с тремя сервисами (telegraf, influxdb, grafana) — это условные 10 минут работы для опытного админа.
Как выглядит “делай раз, делай два” при физическом подключении

Датчик DL-303 подключается по RS-485 двумя проводами к соответствующим клеммам сборщика. Полярность важна — при перепутанных проводах датчик не ответит. На самом датчике через встроенный дисплей выставляются Modbus-адрес (по умолчанию 1), скорость порта (по умолчанию 9600) и параметры 8N1. Запишите эти значения — они понадобятся в конфиге.
На шину RS-485 можно подключить до 32 устройств без дополнительного оборудования. Каждому датчику — уникальный адрес (slave_id). Telegraf опрашивает их последовательно.
Шаг 0. Убедиться, что датчик вообще отвечает
Прежде чем трогать Telegraf, стоит опросить датчик вручную. Для этого подходит modpoll. Если на сборщике уже запущен шлюз mbusd:
modpoll -m tcp -0 -a 1 -r 0 -c 10 127.0.0.1
Флаги здесь важны. -m tcp — транспорт Modbus TCP. -0 включает PDU-адресацию, то есть нумерацию регистров с нуля. -a 1 — Modbus-адрес датчика. -r 0 -c 10 — читать 10 регистров начиная с нулевого.
При успешном ответе вывод будет примерно таким:
root@napi-rk3308b-s:~# modpoll -m tcp -0 -a 1 -r 0 -c 10 127.0.0.1 modpoll 3.11 - FieldTalk(tm) Modbus(R) Master Simulator Protocol configuration: MODBUS/TCP, FC3 Slave configuration...: address = 1, start reference = 0 (PDU), count = 10 -- Polling slave... [0]: 0 [1]: 815 [2]: 3881 [3]: 2639 [4]: 7950 [5]: 1124 [6]: 5223 [7]: 0 [8]: 0 [9]: 0
По документации на DL-303 (или прямо по дисплею датчика — у него есть встроенный экран) расшифровываем регистры:
Регистр |
Параметр |
Множитель (scale) |
0 |
CO (ppm) |
1.0 |
1 |
CO2 (ppm) |
1.0 |
2 |
Влажность (%) |
0.1 |
3 |
Температура |
0.1 |
5 |
Точка росы |
0.1 |

Значение 2639 в регистре 3 — это 263.9, то есть 26.39 C при scale=0.1. Регистр 4 в этой документации не используется, регистр 5 — точка росы.
Если modpoll вернул данные — датчик отвечает. Если нет — проблема в физике (провода A/B, полярность, терминирование) или в адресе. Разбираемся там, потом идем к Telegraf.
Шаг 1. Конфиг Telegraf — Modbus TCP

Создаем файл /etc/telegraf/telegraf.d/dl303.conf. На NapiLinux шаблон можно загрузить через веб-интерфейс NapiConfig — раздел «Датчики» -> «Управление датчиками» -> «Загрузить шаблон». На любом другом хосте это просто текстовый файл.
Полный конфиг с секцией output:
## DL-303 (CO, CO2, температура, влажность) — Modbus TCP [[inputs.modbus]] name = "DL-303" slave_id = 1 timeout = "1s" # mbusd слушает на 127.0.0.1:502 controller = "tcp://127.0.0.1:502" input_registers = [ { measurement="DL-303", name="CO", byte_order="AB", data_type="UINT16", scale=1.0, address=[0] }, { measurement="DL-303", name="CO2", byte_order="AB", data_type="UINT16", scale=1.0, address=[1] }, { measurement="DL-303", name="Humidity", byte_order="AB", data_type="UINT16", scale=0.1, address=[2] }, { measurement="DL-303", name="Temp", byte_order="AB", data_type="UINT16", scale=0.1, address=[3] }, { measurement="DL-303", name="DewPoint", byte_order="AB", data_type="UINT16", scale=0.1, address=[5] }, ] [[outputs.influxdb_v2]] urls = ["http://127.0.0.1:8086"] token = "ВАШ_ТОКЕН" organization = "myorg" bucket = "sensors"
Пройдемся по полям, которые вызывают вопросы чаще всего.
byte_order = "AB" — Порядок байт big-endian. Стандарт для большинства Modbus-устройств. Если значения выглядят бессмысленно — попробуйте "BA". Правильный порядок всегда есть в паспорте датчика.
data_type = "UINT16" — Беззнаковое 16-битное целое. DL-303 отдает данные именно так. Для датчиков с отрицательными значениями нужен INT16. Некоторые устройства отдают float — тогда FLOAT32 или FLOAT32-IEEE, и address принимает два регистра: address = [3, 4].
scale — Множитель, применяется к сырому значению. Для Humidity и Temp ставим 0.1, потому что датчик умножает значение на 10 перед записью в регистр.
address = [N] — PDU-адрес регистра, считается с нуля. Если документация использует нотацию 40001, 40002 (Modbus-нотация) — вычтите 1 и уберите ведущую цифру 4.
Шаг 2. Конфиг для Modbus RTU (датчик напрямую по RS485)
Если шлюза RTU -> TCP нет и датчик подключен физически к порту RS-485 сборщика, меняем секцию подключения:
[[inputs.modbus]] name = "DL-303" slave_id = 1 timeout = "1s" controller = "file:///dev/ttyS3" # RS485-порт на NAPI-C transmission_mode = "RTU" baud_rate = 9600 data_bits = 8 parity = "N" stop_bits = 1 # input_registers — те же, что в TCP-варианте input_registers = [ { measurement="DL-303", name="CO", byte_order="AB", data_type="UINT16", scale=1.0, address=[0] }, { measurement="DL-303", name="CO2", byte_order="AB", data_type="UINT16", scale=1.0, address=[1] }, { measurement="DL-303", name="Humidity", byte_order="AB", data_type="UINT16", scale=0.1, address=[2] }, { measurement="DL-303", name="Temp", byte_order="AB", data_type="UINT16", scale=0.1, address=[3] }, { measurement="DL-303", name="DewPoint", byte_order="AB", data_type="UINT16", scale=0.1, address=[5] }, ]
Имя порта зависит от платформы:
• /dev/ttyS3 — NAPI-C (RK3308)
• /dev/ttyUSB0 — USB-адаптер RS485 на любом хосте
• /dev/ttyAMA0 — Raspberry Pi (аппаратный UART)
Параметры порта (baud_rate, data_bits, parity, stop_bits) должны точно совпадать с тем, что выставлено на датчике. Если хоть один параметр не совпадает — данных не будет, и Telegraf запишет ошибку в лог. Это самая частая причина, почему «датчик молчит».
Даже при прямом RS485-подключении удобнее запустить mbusd и работать через Modbus TCP. Тогда можно параллельно отлаживать через modpoll, не останавливая Telegraf.
Шаг 3. Тестовый запуск до перезапуска службы
Запускать telegraf в тестовом режиме — хорошая привычка. Он выполнит опрос датчика один раз и выведет результат в stdout без записи в базу:
telegraf --config /etc/telegraf/telegraf.d/dl303.conf --test
При успешном опросе вывод будет примерно таким:
> DL-303,host=napi-rk3308b-s CO=0,CO2=815,Humidity=38.81,Temp=26.39,DewPoint=11.24 1718012345000000000
Это Line Protocol — то, что Telegraf запишет в InfluxDB. Реальные числа в выводе означают, что конфиг рабочий. Добились чистого вывода — перезапускаем службу:
systemctl restart telegraf
Теперь про типичные ошибки при тесте:
connection refused — шлюз mbusd не запущен или неверный адрес в поле controller.
i/o timeout — датчик не отвечает. Проверяем slave_id, параметры порта, полярность проводов A/B.
invalid character — синтаксическая ошибка в TOML. Смотрим на кавычки и лишние пробелы.
connection reset by peer — при RTU — скорость или параметры порта не совпадают с датчиком.
Шаг 4. Grafana — дашборд
После того, как данные пошли в InfluxDB, подключаем Grafana. Data Sources -> Add data source -> InfluxDB, Query Language: Flux. URL, токен и организация — те же, что в конфиге Telegraf.
Простейший Flux-запрос для графика температуры:
from(bucket: "sensors") |> range(start: -1h) |> filter(fn: (r) => r._measurement == "DL-303") |> filter(fn: (r) => r._field == "Temp")

Добавьте панель для каждого поля (CO2, Humidity, DewPoint) — дашборд готов. Для DL-303 разумно сразу поставить алерт на CO2 > 1000 ppm и CO > 50 ppm — это нормы по СанПиН для рабочих помещений. Grafana уведомит по email, Telegram или любым другим каналом.
Готовые JSON-шаблоны дашбордов для распространенных датчиков, включая DL-303 можно взять: github.com/lab240/telegraf-grafana-configs.
А если несколько датчиков на одной шине
RS-485 поддерживает до 32 устройств на сегмент без дополнительного оборудования. Каждому датчику нужен уникальный slave_id на шине и уникальное measurement в конфиге. Удобнее всего разложить по отдельным файлам в telegraf.d/ — Telegraf подберет все автоматически при рестарте:
/etc/telegraf/telegraf.d/ dl303-room1.conf # slave_id=1, measurement="DL-303-room1" dl303-room2.conf # slave_id=2, measurement="DL-303-room2" pressure.conf # slave_id=3, measurement="PressureSensor" ## Датчик 1 [[inputs.modbus]] name = "DL-303-room1" slave_id = 1 controller = "file:///dev/ttyS3" ... ## Датчик 2 [[inputs.modbus]] name = "DL-303-room2" slave_id = 2 controller = "file:///dev/ttyS3" ...
Telegraf опрашивает датчики последовательно — один запрос, один ответ. Если 10 датчиков x 500 мс timeout = 5 секунд на цикл, то интервал опроса в 1 секунду нереалистичен. При большом числе устройств увеличивайте timeout или interval.
Что делать с датчиком, если он без документации
Так бывает: датчик на руках, написано только «Modbus RTU, 9600 8N1, адрес 1», а документации нет. Алгоритм простой.
-
Опросить первые 30-40 holding-регистров подряд.
modpoll -m tcp -0 -a 1 -r 0 -c 40 127.0.0.1 Сравнить вывод с тем, что показывает датчик на дисплее или в родном ПО.
Значение 265 при температуре 26.5 C на экране — это регистр с scale=0.1. Значение 4587 при давлении 458.7 гПа — тоже scale=0.1. По таким совпадениям определяем, какой регистр что означает.
Учесть масштаб (scale) — часто датчик отдает значение умноженное на 10 или 100.
Для датчиков с float: некоторые устройства упаковывают 32-битный float в два соседних регистра.
Тогда в конфиге:
{ measurement="MySensor", name="Pressure", byte_order="ABCD", data_type="FLOAT32-IEEE", scale=1.0, address=[3,4] }
Byte_order для float бывает ABCD, DCBA, BADC — перебираем до осмысленного значения.
Графический интерфейс NapiConfig — то же самое без консоли
Весь путь выше пройден через SSH и текстовый редактор. На NapiLinux того же результата можно добиться из веб-интерфейса NapiConfig. Он открывается на порту 443, собран на Vue и FastAPI, ставить отдельно ничего не нужно — интерфейс уже в системе. Три частые операции при работе с датчиками собраны в одном месте. Это правка конфига Telegraf, проверка опроса и просмотр графиков, и все три не требуют консоли и памяти на пути к файлам.

Правка конфига Telegraf. Каждый датчик — это отдельный файл в telegraf.d. В NapiConfig он открывается в редакторе с подсветкой TOML. Правятся те же поля, что в шагах выше — slave_id, controller, адреса регистров, scale, — только без vim по SSH. Рядом кнопки теста и сохранения.

Отладка опроса. Кнопка «Тест» прогоняет telegraf --test на текущем конфиге и показывает результат в окне — строку Line Protocol с реальными значениями, лог Telegraf и код возврата. Это ровно проверка из Шага 3, но вывод идет в интерфейс, а не в stdout. Ошибка в scale, неверный slave_id, молчащий датчик — все увидите, службу перезапускать не надо.

Графики из базы. Раздел «Графики» читает ряды прямо из InfluxDB и строит их по выбранному регистру. Есть выбор поля, временной диапазон и множитель, так что форму сигнала по сырому значению регистра видно без запуска Grafana. Для быстрой проверки «данные идут и выглядят осмысленно» этого хватает. Grafana остается, скажем так, на своем месте — там, где нужны постоянные дашборды и алерты.

Заодно в NapiConfig есть страница Modbus-шлюза — тот самый мост RTU в TCP через mbusd из Шага 0, настраивается мышкой. Плюс управление сетевыми интерфейсами, службами systemd, просмотр логов и веб-терминал SSH на случай, если консоль все-таки понадобится.
Полный разбор стека с нуля есть на Хабре в статье Александра Фролова «Собираем метрики с датчиков через Modbus и Telegraf». Автор ставит Telegraf, InfluxDB и Grafana на разное железо — Raspberry Pi, Orange Pi, Repka Pi и модуль Front Control Compact, — подключает датчики XY-MD02 и PZEM-016 по RS485, разбирает настройку InfluxDB, срок хранения данных и работу через NapiConfig, все с командами mbpoll и скриншотами веб-интерфейса.
Статья А.Фролова будет полезной точкой входа, если стек поднимается вручную, а не на NapiLinux.
Выводы
Весь путь от подключенного датчика до рабочего дашборда:
Физически подключить RS485, убедиться через modpoll что датчик отвечает.
Написать конфиг Telegraf — 15-20 строк TOML.
Прогнать telegraf --test, убедиться что значения на выходе реальные.
Перезапустить службу, добавить панели в Grafana.
Telegraf берет на себя опрос, буферизацию и запись в базу. При потере связи с датчиком он записывает ошибку в лог и продолжает работать — следующий опрос будет через заданный интервал (по умолчанию 10 секунд). При восстановлении связи данные идут дальше без какого-либо вмешательства.
Стек (Telegraf + InfluxDB + Grafana) одинаково работает на ARM-сборщике в цеху и на x86-сервере в серверной. Данные локальны, лицензий нет, сообщества активны.
Хелп:
Веб-страница с диаграммами подключения
https://napiworld.ru/software/sensors/telegraf-modbus/Шаблоны конфигов Telegraf и дашборды Grafana для разных датчиков: github.com/lab240/telegraf-grafana-configs
Документация плагина modbus: github.com/influxdata/telegraf/blob/master/plugins/inputs/modbus/README.md
Если будут вопросы по статье, реализациям или требуется дополнительная информация, просьба писать мне в ЛС.
Комментарии (4)

dmnovikov Автор
07.07.2026 08:37это все теоретические фантазии. если вас в реальный кейс пустят с esp32 на производство, ну пробуйте. ещё софт отдадите (прошивку) и несите по нему гарантию, особенно когда клиенту надо не заббикс.
я могу ещё дешевле чем вы - я возьму wemosd1mini + uart-rs485 за полкопейки по сравнению с вашей esp32.
но меня с таким решением на предприятие не пустят, они купят скорее Овен или Вайренбоар чем алиэкспресс с есп32, которая может отваливать при помехах (а молет и нет).
а если вам надо держать буфер, который страхует правление связи то ваш есп32 много не напишет, вам надо городить свою плату с памятью. и если вам надо не заббикс а интегрироваться в софт заказчика тоже отдельные приключения.
описанный мной метод скорее вообще для одиночных задач черного ящика. берешь Front вешаешь рядом с датчиком пишешь в него, подходишь с езернет или флешкой снимаешь диагностику того же станка.
но битва МК / Linux в ембедед начинается :)) я сам делал решения на esp, у меня есть модбас датчик за полкопейки на esp8266, толкьо почему-то асутпшнико покупают дорогие датчики от вендора когда хотят не домашнюю метеостанцию а телеметрию.
VlygIO
Какая-то очень странная постановка задачи. Для того, чтобы считать несчастные 10 регистров, нужно поставить полноценный комп на линукс. Потом нагородить какой-то очень странный огород из сервисов чтобы что? Показать директору красивые картиночки?
И нет, типичная история при работе с промышленными датчиками так не выглядит.
dmnovikov Автор
чтобы считать и хранить, без скада и облака
VlygIO
ОК, попробую навалить конкретики. Кейс почти что реальный.
У меня есть, предположим, 500 программно-аппаратных комплексов, расположенных по всей области. Питание на объектах смешанное, 230 В переменки/АКБ, соответсвеннно, в качесте контроллера используется DRS-240-12 от MEAN WELL. Стоит эта железяка примерно 13 тысяч рублей и умеет в ModbusRTU поверх RS-485. Связь на объектах уже есть. Соответственно, задача заключается в том, чтобы брать с железяки метрики и класть их в какой-нибудь “считать и хранить, без скада и облака”-сервис. Пожелание заказчика - дело святое.
Теперь у меня есть 2 пути: мой и ваш. Сначала про мой. Я беру железяку у китайцев на базе ESP32, уже с ethernet, RS-485, с 4-мя реле, несколькими свободными входами и даже в корпусе, с возможностью монтажа на DIN-рейку. Плачу за 1 штуку 2 тысячи рублей. Это в рознице, если возьму оптом, дадут ещё много миска риса и почти новый кошко-жена. За 500 штук я отдам 1 миллион рублей, запомните это число. Прошивку залью свою. Метрики буде класть в Zabbix, который, естественно, уже есть, потому что к 2026-му году он давно есть уже у всех, кому это было надо.
Теперь рассматриваем тот путь, который предлагаете вы. На каждый объект мы будем ставить FRONT Compact RUS01, по цене 32 тысячи рублей за штуку. За 500 штук мы отдадим 16 миллионов рублей. Telegraf будем ставить на промышленные компьютеры. Для InfluxDB + Grafana нам понадобится сервер. Мы не лохи, будем собирать скромный но, кластер, из двух нод + q-device. 2 миллиона рублей. Итого 18 миллионов рублей.
Выводов не будет, каждый сделает свои сам. Или не сделает.