Коротко
Мы подписали контракт с одним из ведущих российских производителей лекарств для лечения онкологии. Нужна система мониторинга и управления чистыми помещениями. Счётчики частиц и шкафы управления на объекте уже стоят, не хватает программной части: она должна опрашивать приборы, показывать данные, управлять оборудованием и оставлять доказательную базу для проверок GMP. По сути мы разрабатываем собственную SCADA-систему, российскую, без зависимости от чужих подписок и под требования GMP. Пишем её на платформе Юи и уже знаем, как она будет устроена.
Железо в Россию ввезти можно, с софтом сложнее
После 2022 года оборудование, в том числе американское и европейское, по-прежнему можно купить и ввезти. Это дорого и долго, но возможно, и сам прибор работает как раньше. Проблемы начинаются с программной частью вокруг него:
- Обновления. Фирменное ПО перестаёт получать новые версии. Операционные системы идут вперёд, а старый клиент остаётся на прежней версии и со временем перестаёт запускаться.
- Лицензии. Подписки и ключи привязаны к облачным сервисам производителя, и продлить их из России часто нельзя.
- Техническая поддержка. Инженер вендора не приедет, а тикет в службу поддержки никто не прочитает.
- Облака и внешние сервисы. На фармацевтическом производстве, где на объекте нет интернета, они неприемлемы.
Правила GMP требуют, чтобы компьютеризированная система была валидирована и оставалась в валидном состоянии. Если ПО нельзя обновлять и сопровождать, его приходится менять на то, что обслуживать можно. Российские компании ищут локальные решения, а мы как раз умеем их делать.
Что за оборудование на объекте
Аппаратная часть уже смонтирована:
- Счётчики частиц TSI AeroTrak (серия AeroTrak+). Это американские приборы, мировой стандарт контроля чистоты воздуха. Они считают частицы по каналам ≥0,5 мкм и ≥5,0 мкм, как требует ISO 14644-1, и отдают расход воздуха и статус прибора.
- Шкафы управления с модулями ввода-вывода ОВЕН серии Мх210 (отечественными), которые коммутируют катушки пускателей насосов и заслонок.
- Связь между ними по Modbus (TCP или RTU).
«Родное» программное обеспечение для таких решений либо недоступно, либо не обслуживается, либо не работает в закрытом контуре без интернета. Поэтому программную часть мы пишем сами.
Что мы делаем: свою SCADA-систему
SCADA (Supervisory Control And Data Acquisition) означает диспетчерское управление и сбор данных. Такие системы собирают данные с оборудования, показывают их оператору, сигнализируют об авариях, позволяют управлять механизмами и хранят архив. Обычно для этого берут западные пакеты, и именно с ними сейчас проблемы с лицензиями, обновлениями и поддержкой.
Наша система закрывает все базовые функции SCADA:
| Функция SCADA | Как это у нас |
|---|---|
| Сбор данных | OPS-сервер опрашивает приборы по Modbus TCP и RTU |
| Архив | Измерения с признаком качества в PostgreSQL |
| Визуализация | Дашборд цеха, графики с пределами, в браузере на любом устройстве |
| Аварии и события | Пределы, журнал аварий, подтверждение с причиной и подписью |
| Управление | Реестр разрешённых действий и сценарии «Пуск» и «Стоп» |
| Отчётность | PDF/A с электронной подписью в документообороте |
| Права и аудит | Разграничение доступа и неизменяемый журнал (платформа Юи) |
От классических SCADA нас отличает то, что мы с самого начала пишем систему под фарму: права, журнал, подпись и валидируемость заложены в основу. Система собирается из конфигураций, без программирования под каждый объект, поэтому её можно тиражировать на другие производства.
Наша система не управляет технологическим процессом выпуска продукции и не заменяет аппаратные защиты. Она отвечает за мониторинг чистых помещений и управление вспомогательным оборудованием.
Называется она GoodWay Integrator. Её задача: из набора отдельных приборов собрать единое рабочее место для оператора и для службы качества. Работа разбита на четыре этапа.
Этап 1. Фундамент и подключение. Разграничение доступа, журнал действий, связь с приборами по Modbus и живые данные в интерфейсе. Управлять оборудованием на этом этапе нельзя: система только слушает.
Этап 2. Управление оборудованием. Инженерная панель с полным каталогом сигналов каждого прибора, где каждому регистру дано понятное имя. Затем поштучная проверка каждого выхода на реальном оборудовании по трёхшаговой процедуре: «сухая» проверка, проверка цепей управления и пуск механизма.
Этап 3. Рабочие сценарии и отчёты. Оператор нажимает одну кнопку «Пуск цеха», и система отрабатывает всю последовательность, а оператор видит каждый шаг. К этому этапу относятся также графики частиц с пределами, аварии и их подтверждение, режим обслуживания и отчёты в PDF/A с электронной подписью.
Этап 4. Квалификация (IQ/OQ/PQ). Формальная валидация по GAMP 5. Это отдельный большой объём работы, и он идёт по отдельному соглашению.
Сценарий задаётся настройкой, код при этом не меняется. Добавить цех или прибор и изменить последовательность можно конфигурацией, не трогая программу. Для фармы это существенно: каждое изменение кода проходит процедуру управления изменениями, а любая конфигурация проходит через журнал и подпись.
Почему на платформе Юи
Система строится на нашей платформе Юи, где уже есть всё, на чём держится работа под GMP:
- Пользователи, отделы и шаблоны прав. Оператор, инженер, QA и администратор видят разные разделы. Администратор не может подтверждать аварии, менять пределы и подписывать отчёты. Такое разделение обязанностей требует Приложение 11 к GMP ЕАЭС.
- Журнал действий: кто, что, когда и над каким объектом. Записи нельзя править и удалять, а при изменении настроек фиксируются прежнее и новое значение.
- Парольная политика, двухфакторная аутентификация, автовыход при бездействии.
- Электронная подпись и документооборот. Отчёты хранятся в PDF/A, не редактируются и заменяются только новой версией.
- Единая дизайн-система, чтобы операторам не приходилось привыкать к «инженерному» интерфейсу.
- Адаптивная вёрстка. Интерфейс одинаково работает на компьютере, планшете и телефоне, устанавливать программы на рабочие места не нужно, достаточно браузера. Дежурный инженер может посмотреть состояние цеха и подтвердить аварию с телефона, а оператор у шкафа работает с планшета.
К Юи мы уже подключали реальное оборудование: модуль Гигротермон (мониторинг температуры и влажности) работает у нас в боевом режиме. Тот же подход мы переносим на чистые помещения. Платформа готова к новым модулям, поэтому такие задачи мы берём быстро.
Система делится на два слоя:
- Юи отвечает за людей: вход, права, журнал, подпись, отчёты, интерфейс.
- OPS (наш сервер сбора на Modbus) отвечает за «железо»: опрос приборов, хранение измерений, исполнение разрешённых действий.
Слои общаются по строгому правилу: данные идут из OPS в Юи, а команды идут из Юи в OPS только как вызов заранее описанного действия. Юи никогда не пишет в регистры напрямую. Соответствие «кнопка, устройство, регистр» хранится только в OPS.
Для тех, кому интересны технические детали
Modbus
Modbus придумали в 1979 году, и он до сих пор остаётся основным протоколом промышленной автоматики. Он прост, но на мелочах в нём легко ошибиться.
Адресация. В документации приборов регистры записывают как 40001, 30001, 10001. Это «человеческая» нумерация, где первая цифра обозначает тип таблицы. По сети передаётся смещение внутри таблицы («PDU-адрес»), и вычитать надо разное число: из holding-регистров 40001, из input-регистров 30001, из дискретных входов 10001, из coils 1. Одна ошибка в смещении, и прибор отвечает чужим регистром, причём вполне правдоподобным числом. Поэтому мы выводим PDU-адрес отдельно для каждой таблицы и храним его в карте регистров рядом с «человеческим» номером.
Каталог сигналов. По карте регистров мы строим перечень всех читаемых величин: ключ, функция Modbus, адрес, тип данных, масштаб, единица. Служебные величины (дата прибора, серийный номер, версия прошивки, коды ошибок) идут отдельной группой и не смешиваются с измерениями. При наладке инженер может дать каждому сигналу понятное имя и привязать его к механизму и к цеху.
Профили приборов. Карта регистров, каталог сигналов, перечень выходов и правила отображения собираются в профиль. Новый прибор подключается выбором профиля и указанием адреса. Для разных моделей и прошивок профиль копируется, поэтому изменение базового профиля не ломает уже настроенное.
OPS-сервер
OPS (Modbus OPS) это отдельный сервис, который общается с железом. Он написан на Python и работает как асинхронное приложение:
- FastAPI даёт REST API и интерактивную документацию (OpenAPI), через которую Юи получает данные и вызывает действия.
- pymodbus (asyncio) работает как клиент Modbus TCP и Modbus RTU. Поддерживаются обмен по сети и по последовательному порту (RS-485), а также RTU поверх TCP через шлюзы, которые часто стоят в шкафах.
- SQLAlchemy 2 (async) и asyncpg отвечают за работу с базой данных, Alembic за версионируемые миграции схемы.
- По WebSocket идёт живая лента событий: интерфейс узнаёт о новых измерениях сразу, а не опрашивает сервер по таймеру.
- Аутентификация: токены Юи для людей и API-ключи для интеграций. У ключа хранится только хеш и префикс, сам ключ после выдачи восстановить нельзя.
Внутри OPS три основные части:
- 1Реестр подключений и устройств. Подключение (TCP-адрес или COM-порт, Unit ID, тайм-аут) отделено от устройства (профиль, имя, атрибуты). Через одно подключение, например шлюз RS-485, можно работать с несколькими приборами.
- 2Планировщик опроса. Фоновая задача раз в 500 мс просматривает активные задания опроса и запускает те, у которых подошёл интервал. Каждое задание привязано к устройству, версии карты регистров и, при необходимости, к списку каналов.
- 3Исполнитель Modbus. Он открывает соединение, читает нужные регистры по карте, декодирует их и возвращает значения с признаком качества. О людях и правах он ничего не знает, это дело Юи.
Как мы читаем Modbus
Чтением управляет карта регистров, то есть JSON-описание прибора. Для каждого канала в ней указаны ключ, функция Modbus (holding, input, coils, discrete inputs), адрес, число регистров, тип данных, масштаб, смещение и единица измерения. Код чтения универсален, а специфика прибора лежит в данных, так что новая модель прибора требует новой карты, а программу менять не нужно.
Декодирование. Одно значение в Modbus часто занимает несколько 16-битных регистров. Поддерживаются uint16, int16, uint32, int32 и float32 в обоих порядках слов (big- и little-endian), строки ASCII и специальные декодеры для отдельных приборов. У разных вендоров порядок байтов и слов разный, и ошибка здесь не вызывает сбой, а даёт правдоподобное неверное число.
Качество измерения. Каждое значение сохраняется со статусом good или bad. Если регистр не прочитался, пришло нечисловое значение (NaN, бесконечность) или ответ с ошибкой, канал помечается как недостоверный и не пропускается молча. Для GMP данные должны быть честными и тогда, когда они плохие.
Опрос счётчиков частиц по триггеру. Это наше инженерное решение для TSI AeroTrak. Счётчик сам делает пробы (например, раз в минуту) и записывает результат во внутренний буфер. Если читать все регистры каждые полсекунды, получится куча одинаковых значений, лишняя нагрузка на прибор и мусор в базе. Поэтому мы делаем так:
- 1Каждый тик читаем один регистр, счётчик записей (
sample_record_index). - 2Пока число не изменилось, больше ничего не читаем.
- 3Когда число изменилось, прибор закончил новую пробу. Тогда мы один раз дочитываем блок последней пробы: дату и время, число частиц ≥0,5 и ≥5,0 мкм, температуру и влажность.
На одну пробу прибора приходится ровно одна запись, без дублей и пропусков и с минимальной нагрузкой на Modbus-линию. Дата и время пробы берутся из самого прибора, а не из момента нашего опроса.
Адреса. В картах TSI используется «документальная» нумерация (40001 и далее). В коде везде работает PDU-адрес, то есть документальный номер минус 40001. Именно из-за описанной выше путаницы правило пересчёта вынесено в отдельное требование ТЗ.
Особенности железа. Реальные приборы ведут себя не так, как написано в документации. Например, на практике выяснилось, что удалённый интерфейс AeroTrak не поддерживает функцию «запись нескольких регистров» (FC16) и возвращает ошибку «illegal function». Поэтому ASCII-поля мы пишем последовательностью одиночных записей FC06. Такие нюансы мы фиксируем прямо в профиле прибора.
Диагностика связи. Перед подключением выполняется проверка (probe): сначала пробуется обычный Modbus TCP, затем RTU поверх TCP, читаются holding- и input-регистры. Если ответа нет, пользователь получает подсказку: проверить Unit ID, видимость устройства в сети, межсетевой экран и тип шлюза.
PostgreSQL
Все данные лежат в PostgreSQL 16:
| Таблица | Что хранит |
|---|---|
modbus_connections | Параметры подключения (адрес, порт или COM, Unit ID, тайм-аут) в виде JSONB |
devices | Устройства: профиль, имя, атрибуты |
register_maps | Версионируемые карты регистров: новая версия создаёт новую запись, история сохраняется |
poll_tasks | Задания опроса: интервал, активность, список каналов |
samples | Измерения: устройство, ключ канала, время, числовое значение, сырое значение, признак качества |
audit_logs | Технический журнал операций с типом действия, объектом и подробностями |
api_keys, users | Ключи доступа (только хеши) и аварийные учётные записи |
Несколько решений в этой схеме:
- Время хранится с часовым поясом (
timestamptz), в UTC, а отображается в часовом поясе объекта. - JSONB для карт регистров и параметров подключения даёт гибкость (разные приборы, разные поля), при этом данные остаются проверяемыми и индексируемыми.
- Сырое и числовое значения хранятся рядом. Если декодирование изменится, исходные регистры сохранены, и данные можно пересчитать.
- Составной индекс по
(устройство, канал, время по убыванию)ускоряет самые частые запросы: «последнее значение» и «история пробы». - Миграции Alembic делают каждое изменение схемы версионированным и воспроизводимым шагом. Это основа для IQ и для управления изменениями.
- Для фармы мы дополняем модель: связываем записи журнала контрольными суммами, чтобы вмешательство можно было обнаружить, запрещаем изменение и удаление журнала правами СУБД и вместо физического удаления используем деактивацию. Эти требования описаны в этапе 1.
У Юи и у OPS раздельные базы данных. Измерения живут в OPS, пользователи, права, подписи и отчёты в Юи, и падение одной базы не уничтожает данные другой.
Путь одного измерения
Вот что происходит с одной пробой частиц:
- 1Счётчик закончил пробу и увеличил внутренний счётчик записей.
- 2Планировщик OPS на очередном тике видит новое значение и дочитывает блок пробы по Modbus.
- 3Значения декодируются по карте регистров (
uint32для числа частиц, спецдекодеры для температуры и влажности) и получают признак качества. - 4Измерения записываются в
samples, и тут же рассылается событие по WebSocket. - 5Юи получает данные, показывает их в разделе «Чистые помещения» и сравнивает с пределами для зоны.
- 6При превышении в журнале создаётся авария, которую оператор подтверждает, а система фиксирует, кто, когда и почему.
- 7По окончании периода из тех же данных формируется отчёт PDF/A с электронной подписью, который уходит в документооборот Юи.
Всё это занимает секунды: по ТЗ от прибора до экрана должно проходить не более 5 секунд.
Опрос и целостность данных
- Опрос идёт в фоне по расписанию, каждое измерение получает метку времени (в UTC) и признак качества.
- Если база данных недоступна, измерения буферизуются на несколько минут, потом записываются без дублей. Если буфер исчерпан, пропуск фиксируется как разрыв.
- Разрывы данных на графике остаются разрывами: линия не соединяет точки через пропуск. Для GMP честный график важнее красивого.
- Время на всех компонентах берётся из одного локального источника, потому что интернета на объекте нет.
Команды оборудованию
Запись в оборудование самая рискованная часть, поэтому здесь мы консервативны:
- Только каталог. Запись возможна лишь по адресам из каталога управляемых выходов. Произвольный адрес нельзя указать ни через API, ни через интерфейс.
- Идемпотентность. У каждой команды уникальный ключ, и повторная доставка той же команды не вызывает повторного срабатывания.
- Срок годности. Команда, застрявшая в очереди, не исполняется «потом», а отменяется с записью в журнал.
- Без автоматических повторов. Если команда не выполнилась, система не пытается за пользователя выполнить её ещё раз.
- Обратная связь. После команды OPS читает фактическое состояние с устройства. Расхождение между командой и фактом фиксируется как событие.
- Режим наладки. Прямое управление выходами в обход рабочей логики допускается только в явном режиме, с указанием причины, ответственного и срока. Измерения этого периода помечаются и не попадают в данные мониторинга.
- Электронная подпись для критичных действий.
Безопасность обеспечивает железо
Программное обеспечение не является средством обеспечения безопасности. Всё, что защищает людей и оборудование, должно работать независимо от нас:
- безопасное состояние модуля: при потере связи он сам выключает все выходы;
- переключатель «Местный / Дистанционный» в шкафу: в положении «Местный» команды из системы не исполняются;
- аварийный останов разрывает цепь аппаратно;
- тепловая защита двигателей и защита от сухого хода выполнены аппаратно;
- блокировка «заслонка и насос» выполнена электрически: концевик заслонки включён в цепь катушки пускателя.
Пока эти условия не выполнены и не оформлены актом, мы не начинаем работу с управлением. Управляет софт, защищает железо.
Работа без интернета
На объекте нет интернета, поэтому в системе нет облачных зависимостей, лицензирования через сервер вендора и внешнего ИИ. Система поставляется готовым образом виртуальной машины на гипервизоре заказчика.
Зачем нужен свой программный стек
Российской промышленности нужны решения, которые не зависят от чужих подписок, обновляются по нашему графику, поддерживаются нашими инженерами, работают на русском языке и учитывают отечественные нормативы (GMP ЕАЭС) наравне с международными.
Оборудование мы не заменяем: американские счётчики частиц остаются на своих местах и продолжают считать. Вокруг них мы строим программный слой, который можно поддерживать, обновлять и проверять самим.
Что дальше
Работа начата. Мы будем рассказывать о ходе проекта: об инженерной панели, о первой «живой» кнопке на оборудовании, о том, как проходят испытания безопасного состояния.
Если у вас похожая задача и приборы есть, а программной части нет, напишите нам.
Приборы есть, а программной части нет?
Расскажите о задаче — подскажем, как её решить на платформе Юи.
Написать нам