Если вы хоть раз отлаживали датчик давления на насосной станции или читали регистры частотника через преобразователь USB-RS485, то почти наверняка держали в руках Modbus Poll. Удобная вещь: быстрый опрос регистров, наглядные таблицы. Но это Windows-only, это платно, и это всё-таки только опросчик - без наглядных схем для удобства пусконаладки и тестирования.

Мне захотелось то же самое, но кроссплатформенное, локальное и с возможностью собрать себе маленький операторский экран: цветные аварийные строки, гейджи, окно закреплённых параметров, вычисляемые тэги. Так появился mbSCADA - open-source проект на чистом Rust с UI на Tauri 2 (в дальнейшем переедем на egui, чтобы выглядело более нативно). Проект пишется с помощью ИИ, поскольку я не прогер (каюсь), так что моих познаний в С и Python а так же в языках PLC будет недостаточно дабы кодить это собственными силами, однако я точно знаю что требуется мне от инструмента. Это clean-room реализация: мы не читали исходники Modbus Poll, но формат его конфигурационных файлов .mbp/.mbw поддерживаем byte-exact, чтобы ваши наработанные проекты импортировались без боли.

Ниже — короткий тур по тому, что получилось, как это устроено внутри и где взять готовые сборки.

Зачем ещё один опросчик

В 80% бытовых задач интеграции нужен не монстр вроде полноценной SCADA, а «Modbus Poll с плюшками» - опросить десяток устройств, покрасить аварии, построить экран для оператора и выгрузить архив в CSV, который потом откроют в чём угодно.

При этом требования к инструменту жёстче, чем кажется: он должен запускаться без установки (портабельные версии удобны и неприхотливы к устройству пользователя), не лезть в сеть (никакой телеметрии и облаков — просто нет) а еще собственно полноценно поддерживать Modbus как TCP так и RTU иначе вся затея не имеет смысла. Отсюда и формат проекта: один бинарник ~6 МБ, всё локально, проект — файл рядом.

И да,проект принципиально открытый чтобы любой желающий мог пользоваться и при желании вносить свой вклад, лицензия - MIT. Собирается одним cargo build либо устанавливается через установщик / открывается AppImage.

Совместимость с Modbus Poll: byte-exact импорт

Поскольку на моем месте работы накопился большой багаж файлов Modbus Poll, то во избежании переписывания всего этого добра - работа с «родными» файлами Modbus Poll стала обязательным требованием. В репозитории живёт отдельный крейт mb-format, который парсит .mbp и .mbw и умеет обратную операцию: write(parse(bytes)) == bytes. Это свойство покрыто тестами и проверено на реальных файлах от Modbus Poll 10.5 — раундтрип байт в байт совпадает с оригиналом.

Сохранённые mbSCADA-проекты остаются совместимыми с оригиналом — можно готовить конфигурацию на ноутбуке с Linux, а отдавать коллегам, которые продолжают жить в Modbus Poll.

Опросы читаются все штатные: 01/02/03/04 (coil/discrete/input/holding), записи 05/06/0F/10. Поддержаны разрядности и порядки слов - включая u16_swapped (перестановка слов в 32-битных значениях), без которого половина «китайских» преобразователей читается зеркально. Транспорт — Modbus TCP, RTU (COM-порт), плюс ASCII и ASCII-over-TCP для устройств, которые общаются текстовыми кадрами (конкретно на моем месте смог проверить RTU порт, интересующийся из беседы ОВЕНа вроде смог проверить еще на TCP).

Живые таблицы и правило на каждую строку

Основной экран - таблицы опросов в реальном времени: значение, единицы измерения, качество (good/bad/прочерк при отсутствии связи), спарклайн на строку и время последнего обновления. Цвет строки и её текст задаются деревом правил: в отличие от оригинала, где на строку две цветовые настройки, здесь — ветвящееся дерево до 32 ветвей с приоритетом «первый совпавший».

Практический смысл: на каждую строку можно повесить не только «выше порога - красным», но и динамический текст. Классика жанра - «0 → ЗАКРЫТ, 1 → ОТКРЫТ» для сигнала клапана или расшифровка кода ошибки привода прямо в таблице. Оператору не нужна легенда — он читает состояние словами.

Панель общего вида

Панель общего вида

Аварии: не только цвет, но и панель с квитированием

Цвет в таблице — это хорошо, но когда строк сотни, оператор пропускает «мигающую ячейку». Поэтому важные события выносятся на боковую панель аварий: карточка на каждое активное нарушение (уровни hi / hi-hi / lo / lo-lo), время возникновения, текущее значение и сообщение из правила.

С панелью можно работать как в «большой» SCADA: квитировать по одной или все сразу (сброс мигания, авария остаётся, пока не уйдёт условие), смотреть историю с длительностями каждой просадки, включить звуковой сигнал. Клик по карточке перекидывает к строке таблицы с подсветкой - руками искать не надо.

SCADA-мимика: гейдж, тумблер, бары

SCADA-мимика

SCADA-мимика

Рядом с таблицами есть режим мнемосхемы: тэги выкладываются виджетами на сетку. Есть полукруглый SVG-гейдж (мин/макс/единицы настраиваются двойным кликом, дуга красится по аварийным уровням), кнопка-тумблер для записи on/off значений (05-я функция — пишем в устройство кликом со схемы), бар с настраиваемыми min/max.

Это не полноценный графический редактор, и я за это не борюсь: сетка фиксированных виджетов закрывает 90% задач вида «покажи три температуры и давление» быстрее, чем любой canvas-редактор.

Каждая карточка окна - это ссылка на строку таблицы, а не копия: переименуете тэг, название подхватится автоматически. В карточке - значение с единицами, окрашенное теми же правилами, что и строка таблицы. Состав окна сохраняется в проекте.

Часто может понадобиться разница двух показаний датчиков для оценки, для этого в mbSCADA есть вычисляемые тэги. Дельта двух температур, приведение к инженерным единицам, суммарный расход по трём линиям.

Синтаксис — безопасное подмножество арифметики: + - * / % ^, скобки, функции min/max/avg/abs/sqrt/round/floor/ceil/pow. Переменные - это тэги в фигурных скобках (фигурные скобки позволяют ссылаться на тэги с пробелами и кириллицей) и прямые адреса вида p12:100 - «регистр 100 опроса 12». Пример из демо-проекта:

{T2 рубашка} - {T1 реактор}

Никакого eval и рефлексии: в движке живёт собственный рекурсивный парсер на 400 строк без единой зависимости, который компилирует выражение в AST один раз, а дальше только считает. Ошибки синтаксиса ловятся при вводе в редакторе, ошибки вычисления помечают тэг как «плохое качество». Вычисляемые тэги можно заводить в правила аварий, в гейджи и в watch-окно наравне с обычными.

Диагностика, журнал и CSV-архив и просматриваемые параметры

Три вещи, которые в промышленной эксплуатации важнее красивого UI.

Диагностика - панель со счётчиками по каждому соединению и опросу: ок/ошибки, таймауты, счётчик реконнектов, время последнего успешного обмена. Когда «всё пропало», первое, что нужно знать - пропало ли вообще и когда было хорошо.

Посмотрите на правую сторону, там вы увидите диагностику

Посмотрите на правую сторону, там вы увидите диагностику

Журнал - события движка (RX/WR/ERR/SYS) дописываются в лог-файл с полными таймстампами: каждый цикл обмена, каждая ошибка связи, каждая реконнекция. Разбирается постфактум за минуты.

Архив - настраиваемый CSV-историк значений: либо писать только изменения (компактно), либо все тэги по фиксированному периоду (ровная сетка времени). Архив автоматически возобновляется при перезапуске приложения - файл продолжает дописываться, а не создаётся заново.

А так же - просматриваемые параметры, floating окошко которое позволяет вам отслеживать в любом удобном месте только те регистры которые вам нужны.

Просматриваемые параметры

Просматриваемые параметры

Архитектура: четыре крейта и никакого монолита

Проект - Cargo-workspace из четырёх крейтов плюс приложение: Крейт Что делает mb-proto Кадры Modbus TCP (MBAP), RTU, ASCII, CRC-16, таймауты, ошибки протокола mb-format Парсинг и byte-exact генерация .mbp/.mbw, внутренний формат проекта mb-engine Движок: по потоку на соединение, планировщик сканов, правила, вычисляемые тэги, диагностика mb-sim Виртуальные Modbus-слейвы для интеграционных тестов без железа

UI - ванильный JS поверх Tauri 2, без React/Vue/бандлеров: HTML + один main.js, который общается с движком через invoke. Это сознательный выбор - интерфейс специфический и табличный, ценность фреймворка тут минимальна, а цена (сборочный конвейер, размер, время старта) вполне ощутима. Как результат - установщик в единицы мегабайт и мгновенный старт.

Всё это покрыто тестами (68 на момент v1.2), CI гоняет их на Linux и Windows, а релизная механика по тегу v* автоматически собирает пять платформ: Windows x64 (NSIS/MSI), Linux x86_64 и aarch64 (AppImage/deb), macOS Apple Silicon и Intel (dmg). Быстрый старт

Самый короткий путь — забрать готовый установщик со страницы релизов: github.com/kostyk348/mbscada-rs/releases/latest. Windows - exe/msi, Linux - AppImage (запускается без установки), macOS - dmg.

Сборка из исходников, как положено, тривиальна:

git clone https://github.com/kostyk348/mbscada-rs cd mbscada-rs cargo build --release -p mbscada

Интерфейс двуязычный (RU/EN), переключается одной кнопкой в тулбаре; документация в репозитории тоже на обоих языках. Планы

В планах - история аварий с фильтрами и выгрузкой, полноценные тренды по вычисляемым тэгам, больше настроек архивирования, расширение набора виджетов мимик. Репозиторий открыт под MIT, issues и PR приветствуются - особенно интересно обратной связи от людей, которые гоняют Modbus в бою: какие кодеки, тайминги и форматы встречаются в реальности.

Проект: github.com/kostyk348/mbscada-rs · Релиз v1.5.2 · Лицензия MIT