Задание на станок уходит одной кнопкой. Приложение — одним файлом
Программа стоит на компьютере рядом с линией сверления и отреза. Забирает производственные задания из учётной системы, раскладывает номенклатуру на конкретные отрезки профиля, показывает мастеру, что уйдёт на станок, и отправляет пакет по протоколу оборудования. Ни сервера, ни установщика, ни прав администратора — исполняемый файл и всё.
Между заданием и станком стоит человек с калькулятором
Мастер открывает задание, смотрит номенклатуру, в уме умножает комплект на план, выписывает размеры на бумажку и вбивает их в панель станка. Каждая цифра проходит через руки дважды, и каждая может поехать.
Ошибка стоит профиля целиком
Перепутанный размер — это отрезанный не так профиль. Материал в лом, время участка потеряно, срок сдвинулся.
Ручной пересчёт съедает смену
Комплект на десяток позиций — это сотня отрезков, которые кто-то считает вручную перед каждым запуском.
Незаполненный атрибут всплывает у станка
Если у номенклатуры не проставлена длина профиля, узнают об этом в момент запуска — когда линия уже освобождена под задание.
Второй запуск даёт другой результат
Тот же заказ, другой мастер — другая раскладка. Сравнивать выработку между сменами не с чем.
Настольное приложение, а не «ещё одна вкладка в браузере»
Компьютер участка живёт в той же сети, что и станок, и часто вообще без выхода наружу. Ставить туда сервер, базу и веб-приложение — значит завести отдельную инфраструктуру ради одной кнопки. Поэтому это десктоп: программу приносят на флешке, кладут на рабочий стол и запускают.
- ▸Один
.exeпримерно на 60 МБ — внутри и код, и графический клиент. - ▸Python на машине не нужен, устанавливать нечего, права администратора не спрашиваются.
- ▸Собирается одной командой примерно за минуту; версия и метаданные подтягиваются из проекта, а не вписываются руками.
- ▸Сборка не требует тяжёлого C++-тулчейна — это отдельный путь, сделанный именно ради простоты выпуска.
- ▸Тот же код собирается в
.app— интерфейс родной, а не веб-страница в окне. - ▸Сборка идёт на CI, потому что бандл для macOS может собрать только macOS. Тег в репозитории — и готовый архив лежит в релизе.
- ▸Пути к настройкам и журналам берутся системные для каждой платформы, а не «папка рядом с программой».
- ▸Права на сетевые соединения объявлены в метаданных сборки — иначе система молча режет исходящие запросы.
Никакого «версия для мака отстаёт»
Обе платформы собираются из одного проекта одними и теми же метаданными. Разница только в команде сборки.
Что будет при первом запуске
Приложение не подписано, поэтому macOS придержит первый запуск. Для внутреннего инструмента это снимается одной командой или пунктом «Открыть» в контекстном меню — и это описано в документации, а не выясняется на объекте.
Четыре экрана и ни одного ручного ввода размеров
Список заданий с поиском и страницами
Задания приходят из учётной системы вместе с датой, статусом и числом позиций. Мастер находит нужное поиском, а не листает журнал.
Разбор номенклатуры в комплект профилей
По каждой позиции читаются атрибуты — длины, количества, точки сверловки — и собирается комплект, размноженный на плановое количество. Типы профилей вынесены в справочник: новый тип добавляется записью, а не правкой разбора.
Сводка и список замечаний
Сколько отрезков и какой суммарной длины уйдёт на станок — и отдельно позиции, у которых атрибуты не заполнены или не распознаны. Проблема видна до запуска, а не у линии.
Отправка с подтверждением
Перед отправкой — вопрос «точно?». Рядом кнопки «скопировать адрес пакета» и «открыть в браузере»: если что-то пошло не так, наладчик повторит запрос руками и увидит сырой ответ оборудования.
Станок отвечает «200 OK» и на принятый пакет, и на отклонённый
Протокол реализован по документации производителя линии. Смысл работы — не «отправить запрос», а не дать участку решить, что задание ушло, когда оно не ушло.
Сначала спрашиваем, готов ли станок
Занятое оборудование молча игнорирует команды — ни ошибки, ни отказа. Поэтому перед отправкой запрашивается состояние, и пока линия работает, отправка блокируется с человеческим объяснением.
Разбирается тело, а не код ответа
Реальный итог лежит внутри страницы, которую возвращает станок: принят пакет или отклонён, и с каким кодом ошибки. Код HTTP тут ничего не значит.
Одинаковые отрезки сливаются в один блок
Вместо тридцати повторов уходит три блока с количеством. На реальном задании пакет сократился с 1216 до 157 байт — это разница между «не влезло в ограничение» и «ушло с запасом».
Кириллица кодируется по приложению документации
Имя клиента и код заказа попадают на панель станка. Неподдерживаемые символы отбрасываются с предупреждением — иначе панель отвечает кодом ошибки, который на участке никто не расшифрует.
| Поле пакета | Ограничение оборудования |
|---|---|
| размер отрезка | до 4 цифр — не длиннее 9999 мм |
| количество | до 3 цифр — не больше 999 штук |
| сверловка | не более двух отступов на отрезок |
| код заказа | не длиннее 8 символов |
| имя клиента | не длиннее 12 символов |
| пакет целиком | до 100 заданий и не больше 2953 байт |
Все шесть проверяются до отправки. Нарушение — это понятное сообщение в интерфейсе, а не отказ станка спустя секунду.
Браузер страницу показывает. Библиотека — падает
Промышленный контроллер отдаёт страницу, длина которой не сходится с тем, что он сам объявил в заголовке. Строгая HTTP-библиотека дочитывает тело ровно по объявленной длине, оставшийся хвост закрывающего тега принимает за начало следующего ответа и падает с ошибкой разбора. Тот же адрес, открытый в браузере, показывает страницу без единого замечания.
Чинить контроллер нельзя — это оборудование, прошивка чужая. Значит, снисходительным должен стать клиент: для станка написан отдельный транспорт, который отправляет строку запроса байт в байт как в документации и читает ответ до конца страницы, а не до объявленной длины.
Остальное приложение при этом продолжает работать через обычный HTTP-клиент. Исключение сделано ровно для одного узла, а не размазано по всему коду.
Проверка связи без интерфейса
Отдельная консольная утилита стучится по адресу станка и печатает сырой ответ целиком. Наладчику на объекте не нужно запускать программу и гадать: видно, отвечает ли оборудование и что именно оно прислало.
Сутки работы участка — в файле
Журнал пишется с суточной ротацией в системный каталог платформы. Разобрать вчерашний инцидент можно, не подключаясь к машине удалённо.
Пять слоёв, зависимости строго в одну сторону
Приложение маленькое, но живёт рядом с оборудованием и будет меняться: появится новый тип профиля, другая линия, другая учётная система. Поэтому границы проведены сразу.
Модели и справочники без ввода-вывода
Неизменяемые объекты-значения, справочник типов профилей, иерархия ошибок и узкие интерфейсы: у шлюза станка две операции, у сборщика пакета — одна.
Загрузка → разбор → сведение → пакет
Сценарий зависит только от интерфейсов домена, а конкретные реализации подставляются в единственной точке связывания.
Логика проверяется без станка и без сети
Подменный источник заданий и подменный шлюз — и вся цепочка разбора и сборки пакета прогоняется на столе. Оборудование для этого не нужно.
Новый профиль — запись в справочнике
Типы профилей и ограничения протокола вынесены из кода разбора. Добавить четвёртый тип или переехать на другую линию — это данные и одна реализация интерфейса, а не переписывание.
Python на десктопе — без Electron и без браузера
Если между вашей учётной системой и станком стоит человек
Раскрой, гравировка, сварка, покраска, фасовка — везде, где задание переносят на оборудование руками, этот перенос можно сделать одной кнопкой. Даже когда у станка свой самодельный протокол, а документация к нему — файл на двадцать страниц.
Похожие задачи в других отраслях
Курьерская CRM
Скан QR, подготовка заказов и пробег превращаются в готовый табель к концу смены.
смотреть кейс → Строительство · SaaSMetis One
Мультиарендная платформа сметного расчёта: техкарты, живые цены поставщиков, импорт чужих Excel-смет.
смотреть кейс → Безопасность · железоСКУД v2
Проход по карте и лицу, мгновенный перехват на всех точках, табель рабочего времени.
смотреть кейс →