← Back to Articles

Как я приводил заводские данные в порядок: документация, миграция и ClickHouse

Я недавно работаю на заводе ML-инженером, и довольно быстро понял простую вещь: модель — это не только ноутбук, фичи и метрики.

До модели ещё надо добраться через документацию, старые базы, странные выгрузки, ограничения по безопасности и вопрос “а этим данным вообще можно доверять?”.

Про конкретное оборудование и организацию рассказывать нельзя, поэтому дальше без названий. Но сама история типовая для промышленной автоматизации: есть станок, есть PLC, есть HMI, есть регистры, сбора данных вообще нет, но есть новая схема хранения. И всё это надо аккуратно соединить так, чтобы ничего не потерять и не сломать.

Сначала — не код, а понимание источников

Самое неприятное в заводских данных — они редко лежат в одном красивом месте. Часть информации в мануалах, часть в электрических схемах, часть в HMI, часть дали китайцы/европейцы и другие партнеры, а часть нужно будет проверять напрямую через PLC (бомбить PLC с трясущимися коленками).

Поэтому первым шагом был не “давайте быстрее обучим модель”, а сбор и структурирование того, что вообще есть.

Коллега собрал архив с мануалами и электрическими схемами. Из этого отдельно выгрузили информацию по D-регистрам и общую информацию по станку. Полноценный анализ всего архива сразу не делали — времени на это не было. Но уже сама выгрузка в структурированном виде, например в md и json, сильно меняет ситуацию.

Когда регистры лежат только в PDF или в схемах, они существуют как “документация”. Когда они превращаются в нормальный каталог, с ними уже можно работать как с данными: искать, сравнивать, проверять, связывать с будущими сигналами коллектора.

Почему каталог сигналов важнее, чем кажется

В ML обычно хочется быстрее получить таблицу: timestamp, признаки, таргет. Но на производстве нельзя просто брать адреса из воздуха иначе потом непоймешь что искать и главное где.

Нужно понимать:

  • какой это тип устройства или регистра;
  • как его безопасно читать;
  • можно ли его читать группами;
  • что означает сигнал хотя бы примерно;
  • насколько мы уверены в этом смысле;
  • из какого документа пришла информация.

Поэтому отдельной задачей стало продумать структуру “книг” сигналов. В моём случае это YAML-книги, из которых потом можно строить план чтения. Такой подход удобен тем, что один и тот же каталог можно использовать и для проверки, и для будущего коллектора.

Например, smoke-test должен брать одну YAML-книгу, доставать из неё адреса, читать их со станка через MC/SLMP и сохранять результат. Не угадывать смысл сигнала, не делать выводы уровня “станок сейчас в таком-то режиме”, а просто отвечать на базовые вопросы:

  • адрес читается или нет;
  • какое текущее значение;
  • есть ли ошибки по группе адресов;
  • какая задержка чтения;
  • можно ли этот тип сигналов включать в будущий collector (где как раз мы их будем накапливать для ML модельки).

Это скучная работа, но именно она потом экономит много времени. Если адрес не читается, лучше узнать это на smoke-test, а не во время сбора датасета для модели.

Тут действует принцип доверяй, но проверяй.

Безопасность: только read-only и без подвигов

В промышленной автоматизации есть важное правило: если не уверен — не пиши.

Для smoke-test я заложил жёсткие ограничения:

никаких write-команд
никаких force-команд
никаких reset-команд
никаких batch-write
только read
один поток чтения
одна активная MC/SLMP-сессия
между группами чтения короткая пауза

И как вы понимаете, сначала надо было в этом разобратся (АСУ ТП - привет).

Для выходов PLC — только чтение состояния. Для D-регистров, связанных с параметрами, — только чтение как word, без записей в recipe, servo или другие настройки.

Это может звучать слишком осторожно, но на заводе осторожность — не бюрократия, а нормальный инженерный инстинкт, потому что если "отрыгнет" станок за 1,5кк$ мало никому не покажется. Smoke-test должен безопасно показать, какие адреса доступны для чтения.

SQLite как первая версия

Дальше началась отдельная история с хранением данных.

Важно уточнить: никакой старой унаследованной базы, которую кто-то до меня вёл годами, не было. SQLite появилась потому, что на первом этапе мне нужно было быстро и безопасно начать писать данные. Я ещё не до конца понимал, как правильно разложить архитектуру, поэтому первый collector был сделан через SQLite: локально, понятно, без лишней инфраструктуры. Казалось бы, что может пойти не так?

Для первой версии это нормальный путь. Лучше начать собирать данные простым способом, чем месяцами рисовать идеальную схему и в итоге не иметь вообще ничего (System Design - привет)

Но потом простая схема начала упираться в реальность.

Collector постоянно писал в SQLite. Exporter тоже хотел работать с этой же SQLite: читать очередь, проверять строки, подтверждать перенос, убирать уже отправленное. В итоге из-за гонок вокруг записи и выгрузки collector всё время занимал базу, очередь накапливалась, а нормальный перенос в ClickHouse начинал мешать самой записи данных.

То есть проблема была не в том, что SQLite плохая сама по себе. Проблема была в том, что она стала одновременно:

  • локальным хранилищем;
  • очередью;
  • источником для переноса;
  • местом, куда активно пишет collector.

На маленьком объёме это ещё терпимо. Но когда данные идут постоянно, такая схема быстро превращается в пробку.

Далее я пришел к решению избавится от SQL и писать данные бачами прям в ram заводского пк, а оттуда отправлять их по апи на сервер с ClickHouse. Подробную схему тут описывать не буду, т.к. это предмет отдельной статьи.

Почему ClickHouse здесь хорошо ложится

ClickHouse удобен не потому, что это модная БД, а потому что заводские данные очень быстро становятся историей измерений.

Там много строк, много временных меток, много повторяющихся запросов по периодам, сигналам и идентификаторам. Для такого сценария ClickHouse подходит естественнее, чем локальная SQLite. Да и вообще для большого временного ряда - мастхэв.

SQLite в моём случае была хорошей первой ступенькой: быстро начать (ГЛАВНОЕ), проверить подход, не усложнять старт. Но когда появляется нормальная история, аналитика и будущий ML-контур, хочется уже не просто “куда-то писать”, а иметь базу, в которой удобно проверять данные и быстро доставать нужные срезы.

К вопросу о ClickHouse, кто еще переварит столько данных за неделю сбора: 2676886030 (да это число показателей собранных со станка за неделю, а не номер билета)

Практическая польза: что я бы забрал в любой похожий проект

Если коротко, мой чек-лист после этой работы такой.

1. Сначала каталог, потом collector

Не надо начинать с чтения всех адресов подряд. Лучше собрать книги сигналов: адрес, тип, источник, примерный смысл, уверенность, категория. Это потом поможет на этапе обучения ML модели.

2. Smoke-test должен быть read-only

Его задача — проверить доступность чтения, а не “пощупать станок”. Никаких write, force, reset. Один поток, одна сессия, паузы между группами. Документацию конкретного PLC надо изучать отдельно (будь то митсубиси или сименс)

3. Простая первая архитектура — это нормально

SQLite как первая версия не была ошибкой. Ошибкой было бы считать, что временная схема обязана навсегда остаться основной.

Иногда правильно сначала собрать данные простым способом, а потом спокойно вынести историю в более подходящее хранилище чем месяцами разрабатывать идеальную архитектуру.

4. Очередь сама себя не спасает

Если collector пишет в ту же базу, из которой exporter пытается выгружать и подтверждать строки, надо заранее думать про блокировки, гонки и рост pending-очереди.

Если очередь копится и начинает мешать записи — это уже не “техническая мелочь”, а сигнал, что архитектуру пора разделять.

Вывод

В этой работе не было красивого момента “нажал кнопку — и сбор сигналов для ML заработал”. Зато был более полезный результат: данные начали превращаться из набора разрозненных кусков в управляемую систему и главное ПОНЯТНУЮ систему.

Документация стала каталогом. Для PLC появился безопасный read-only подход к smoke-test. Первая версия collector дала реальные данные, а потом эти данные аккуратно переехали из SQLite в ClickHouse.

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

More articles