Industry 4.0 · цифровые двойники станков и промышленной автоматики · отечественная R&D-разработка +7 925 353-56-35 info@synctwin.ru

API и интеграция

Всё, что видит платформа, доступно снаружи по HTTP: описание API, каталоги операций, состояние оборудования, сухой прогон программы. Правило одно и оно не настраивается — наружу отдаётся чтение и проверка, движение станка остаётся за человеком. Ниже — путь от первого запроса до разобранной программы, с точными адресами и текстами отказов.

Шаг 1

Войти и получить токен

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

curl -s https://cncai.ru/api/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"username":"…","password":"…"}'

Что увидите. Ответ вида {"access_token":"eyJ…","token_type":"bearer","expires_in":…,"user":"…"}. Поле expires_in — остаток жизни токена в секундах; срок задаётся на установке переменной AICNC_JWT_EXPIRES_HOURS, поэтому его не надо зашивать в свой код — читайте из ответа. Дальше токен идёт заголовком:

Authorization: Bearer <access_token>

Там, где заголовок послать нельзя — ссылка в браузере, картинка, сторонний генератор клиентов, — тот же токен принимается параметром ?token=…. Это касается и самой спецификации: /api/openapi.json?token=… открывается инструментом, который умеет только URL.

Шаг 2

Выдать внешней системе токен только на чтение

Свой рабочий токен наружу отдавать не нужно. Полным токеном выпускается отдельный, читающий — им и живёт интеграция или ассистент:

curl -s -X POST https://cncai.ru/api/auth/assistant-token \
  -H 'Authorization: Bearer <ваш полный токен>'

Что увидите. {"access_token":"…","scope":"assistant","expires_in":…}. Поле scope — и есть ограничение.

Что этот токен может

  • любое чтение — GET, HEAD, OPTIONS по всему API;
  • сухой прогон программы автоматики — POST /api/automation/validate;
  • предпросмотр заготовки детали — POST /api/cad/templates/{id}/manifest;
  • пересчёт цепочки реза — POST /api/cutting-chain/check: арифметика по присланным числам, ничего не меняющая.

Чего не может — никогда

Любой другой POST получает 403 с текстом «Токен ассистента: только чтение и превью (validate/manifest). Исполнение на станке — через основной UI с человеком». Это закрытый список разрешённого, а не открытый список запрещённого: новая исполняющая ручка автоматически оказывается запрещена, а не наоборот. Под запрет попадают пуск стенда, отправка программы, базирование, толчок оси, ручной кадр, создание станка из конструктора.

Почему это не снимается правами. Читающий токен рассчитан на внешнюю систему и на языковую модель — субъекта, который может ошибиться уверенно. Дописать ему исполнение значило бы отдать движение железа внешнему боту, то есть отменить причину, по которой ограничение вообще заведено.

Шаг 3

Взять описание API

Описание не пишется руками и не может отстать от кода — оно порождается самим приложением из его же схем:

GET /api/openapi.json     машиночитаемое описание: пути, схемы, коды ответов
GET /api/docs             то же самое человеку — страница с формой «попробовать»

Что увидите. Обычный документ OpenAPI: по нему генератор клиентов соберёт библиотеку на вашем языке, а ассистент — список доступных вызовов с типами полей.

Спецификация лежит именно под /api/, а не в корне: наружу маршрутизируется только этот префикс, и по корневому адресу описание из-за периметра не открывалось. Если ваш инструмент по привычке идёт на /openapi.json и получает 404 — поправьте базовый адрес, ручка не пропала.

Шаг 4

Прочитать каталог операций

Каталог отвечает на вопрос «что оборудование умеет и какие параметры принимает» — и отвечает схемой, а не прозой. Каталогов два, по числу движков генерации:

GET /api/generators           операции реза: параметры, единицы, границы
GET /api/automation/catalog   операции автоматики: шаги, условия, предельные значения

Что увидите у операции реза. Кроме имени и описания — список параметров, и у каждого: key (как звать в запросе), label (как зовут человеку), type, default, min / max / step, unit («мм», «°», «об/мин»), options для списков и required. Этого хватает, чтобы внешняя система построила форму или проверила значение до отправки.

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

Каталог реза отдаёт операции обоих родов. Различает их поле discipline: cut — траектория выводится из объёма детали, motion — траекторию называет автор. Фильтруйте по нему, а не по имени.

Шаг 5

Проверить программу, не касаясь железа

Перед тем как что-то отправлять, программу можно разобрать полностью — тем же строгим разбором, который потом валит настоящий прогон:

POST /api/automation/validate    {"spec": {"kind":"mode_blocks", …}}
POST /api/automation/preflight   то же тело — но про сопоставление с железом

Что увидите. validate вернёт {valid, errors, human_steps}. Поле human_steps — разбор шагов по дорожкам человеческими словами; его и надо показать оператору перед отправкой, а не свою пересказанную версию. preflight вернёт {ok, unmapped} — какие серво и входы-выходы программа использует, но со слейвами стенда они не связаны.

Сухой прогон отвечает 200 даже когда программа плоха. Вердикт лежит в valid, а не в коде ответа: разбор состоялся, ошибок в нём — список. Клиент, читающий только HTTP-код, примет неверную программу за проверенную.

Проходит разбор ≠ поедет на железе. validate ничего не знает о том, сопоставлены ли оси с приводами и включено ли питание. Это разные вопросы, и второй задаётся отдельно — preflight.

Справочно

Ручки интеграционного слоя

Метод и путьЧто делаетТелоЧто вернётКому доступно
POST /api/auth/login Обменять логин и пароль на JWT. { "username": "…", "password": "…" } { access_token, token_type: "bearer", expires_in, user } — expires_in в секундах. без токена
GET /api/auth/me Проверить, что токен ещё жив. Ровно это делает веб-интерфейс при загрузке. { user, ok: true } любой токен
POST /api/auth/assistant-token Выпустить токен только на чтение — для внешней системы или ассистента. { access_token, token_type: "bearer", expires_in, scope: "assistant" } только полный токен
GET /api/openapi.json Машиночитаемое описание всего API: пути, схемы тел и ответов, коды. Стандартный документ OpenAPI. Принимает и заголовок Bearer, и ?token=… — второе для инструментов, которые не умеют слать заголовки. любой токен
GET /api/docs То же описание человеку — интерактивная страница Swagger UI. Страница со списком ручек и формой «попробовать». любой токен
GET /api/generators Каталог операций: что платформа умеет генерировать и какие параметры берёт. Массив описаний. У каждого: id, name, description, category, discipline и params — список параметров с key, label, type, default, min, max, step, unit, options, required. любой токен
GET /api/generators/{id} Описание одной операции. То же описание, одной записью. любой токен
GET /api/automation/catalog Каталог операций автоматики: чем описывается шаг программы узла. Реестр операций спецификации (CSV / CSP / CST / DO / WAIT / PAUSE): параметры с типами, умолчаниями и границами, схема условий перехода, предельные значения безопасности и формат самой спецификации. любой токен
POST /api/automation/validate Сухой прогон: проверить программу узла, ничего не двигая. { "spec": { "kind": "mode_blocks", … } } { valid, errors, human_steps } — human_steps это разбор шагов по дорожкам человеческими словами, для показа оператору ДО отправки. любой токен, включая читающий
POST /api/automation/preflight Проверить, что все серво и входы-выходы программы сопоставлены с железом узла. { "spec": { … } } { ok, unmapped: [ { kind, index, label, reason } ] } — тот же гейт, что валит настоящий прогон, но заранее и списком. любой токен

Полный список ручек — в самой спецификации: /api/openapi.json. Здесь только те, с которых начинается интеграция.

Отказы

Что вы получите, когда что-то не так

Тексты приведены дословно — по ним отказ и опознаётся в логе.

КодТекстЧто это значитЧто делатьГде
401 Требуется авторизация Токена в запросе нет, он просрочен или испорчен. Получить новый через POST /api/auth/login. Заголовок — Authorization: Bearer <токен>. middleware
401 Неверный логин или пароль Ответ один и тот же и на несуществующего пользователя, и на неверный пароль — чтобы перебором нельзя было выяснить, какой логин существует. Проверить обе строки. По коду ответа отличить одно от другого нельзя, и это сделано намеренно. POST /api/auth/login
401 Missing token Запрос на выпуск читающего токена пришёл вообще без токена. Сначала войти самому, потом выпускать токен ассистенту. POST /api/auth/assistant-token
403 Только полный токен может выпускать ассистентские Читающий токен попытался выпустить себе ещё один. Ассистент не клонирует сам себя — иначе ограничение обходилось бы одним вызовом. Выпускать читающие токены только полным токеном человека. POST /api/auth/assistant-token
403 Токен ассистента: только чтение и превью (validate/manifest). Исполнение на станке — через основной UI с человеком. Читающим токеном вызвали что-то исполняющее: пуск, отправку программы, базирование, толчок оси, ручной кадр. Это не ошибка настройки и не снимается правами: движение станка остаётся за человеком в интерфейсе. Внешней системе доступны чтение, каталоги и сухой прогон. middleware
404 Генератор не найден Запрошен id операции, которого в каталоге нет. Сверить со списком GET /api/generators — там актуальные id. GET /api/generators/{id}
200 { "valid": false, "errors": [ … ] } Сухой прогон — не отказ HTTP: разбор всегда возвращается со статусом 200, а вердикт лежит в поле valid. Читать valid, а не код ответа. Тексты в errors — те же, что увидит оператор при настоящем прогоне. POST /api/automation/validate
Границы

Чего интеграционный слой не делает

  • Не двигает станок по внешней команде. Исполнение доступно только полному токену человека в интерфейсе. Отдельного «токена с правом на движение» не существует — не потому, что не сделали, а потому, что через границу облака проходит замысел (программа, «выполняй», «стоп»), а не жест: толчок оси, ручной кадр, запись параметра привода живут у станка.
  • Не даёт настраивать область токена по частям. Областей ровно две: полная и читающая. «Только этот станок», «только эта организация», «только на сутки» снаружи не выбираются.
  • Не отзывает выпущенный токен. Читающий токен живёт до истечения срока; кнопки «погасить» нет. Выдавайте с прицелом на это.
  • Не шлёт события наружу. Вебхуков и подписок для внешних систем нет: состояние читается опросом.
  • Не считает сухой прогон допуском к работе. Он проверяет программу, а не готовность оборудования: сопоставление с железом, питание приводов, замеренный вылет инструмента — отдельные гейты, и они срабатывают позже.

Нужен доступ к интеграции или разбор сценария — напишите нам.