Введение
В крупных BIM-проектах часто возникает необходимость выполнять одни и те же операции для множества моделей. Это может быть экспорт в различные форматы (NWC, IFC), извлечение данных для последующего анализа или даже более сложные задачи, связанные с автоматизированной обработкой моделей.
Когда моделей становится слишком много, выполнение этих операций вручную становится неэффективным, а в случае работы с Revit и Navisworks — еще и ресурсоемким. Оптимальное решение — организовать серверную оркестрацию этих процессов, где задания выполняются автоматически по заданному сценарию.
В этой статье мы рассмотрим, как можно настроить управление процессами Revit на сервере, чтобы выполнять BIM-задачи в пакетном режиме. Такой подход позволяет:
- Автоматизировать экспорт моделей в форматы NWC и IFC.
- Выгружать данные из моделей в базу данных.
- Выполнять любые другие задачи, которые необходимо повторять для каждой модели компании.
Оркестрация этих процессов на сервере значительно сокращает время обработки, устраняет человеческий фактор и делает работу с моделями более предсказуемой и управляемой.
Контроллер для работы с очередью задач Серверная часть API уровень
Этот контроллер представляет собой упрощенный пример API, который управляет очередью задач в памяти сервера. Основная цель — показать, как можно добавлять и извлекать задачи с помощью ConcurrentQueue.
Как работает этот контроллер
- Метод Get() – Возвращает элемент из очереди и удаляет его, чтобы задачу дважды в работу не попала
- Метод Post(string value) – добавляет новую задачу в очередь. В реальном сценарии это может быть путь к файлу или информация о задаче.
Ограничения этого решения
- Очередь хранится в памяти (ConcurrentQueue<string>), что означает, что задачи теряются при перезапуске сервера.
- Такой подход не подходит для многосерверной среды (при горизонтальном масштабировании).
- Нет механизма повторного выполнения задач или отслеживания их состояния.
Что использовать в реальном проекте?
Для надежной обработки задач лучше использовать брокеры сообщений:
- RabbitMQ – популярный брокер сообщений, хорошо подходит для распределенной обработки задач.
- Kafka – если требуется высокая пропускная способность и обработка событий в реальном времени.
- Azure Queue Storage или AWS SQS – если приложение развернуто в облаке.
- Redis (List) – можно использовать как простую распределенную очередь с возможностью сохранения данных.
Если тебе нужно внедрить RabbitMQ или другой брокер в этот проект, могу помочь с этим, пиши в тг.
Описание класса RevitRunner, используется на серверной части, вынесен в библиотеку
Класс RevitRunner предназначен для запуска Revit с использованием журнала (journal file). Этот журнал может содержать команды, например, для автоматической выгрузки NWC или выполнения других задач.
🔹 Как это работает?
- Создаем объект RevitRunner, указывая путь к файлу журнала (.txt) и версию Revit, который нужно запустить.
- Вызываем метод Run(), чтобы запустить процесс Revit с переданными аргументами.
- Если нужно принудительно закрыть Revit, вызываем метод Kill().
- При уничтожении объекта RevitRunner (деструктор ~RevitRunner()), Revit автоматически завершается. Но рекомендуется самостоятельно вызывать метод Kill
После того как написали обертку для запуска процесса Revit нам нужно временно перейти к настройке и написанию плагина под Revit
Шаг 1: Создание файла манифеста
Первым делом необходимо написать файл манифеста для нашей команды. Этот файл определит параметры и настройки для плагина.
Шаг 2: Обновление файла журнала
Затем нужно вызвать нашу команду в файле журнала (Runner.txt). Важно, чтобы ID команды в файле манифеста и в журнале были одинаковыми. Эта согласованность критически важна для правильного выполнения и отладки.
Обратите внимание чтобы id команды в файле манифеста и журнале были одинаковы
Шаг 3: Реализация команды
После настройки манифеста и журнала переходим к третьему шагу — написанию команды, которая будет выполнять задачи внутри Revit.
Данный класс RevitCommand реализует интерфейс IExternalCommand, что позволяет вызывать его из Revit. Он работает в бесконечном цикле, запрашивая сервер на наличие новых задач. Если задача найдена, она передается в обработку.
Метод Execute — это точка входа команды в Revit. Он просто запускает ProcessQueue(), который работает в вечном цикле.
Метод ProcessQueue:
- Отправляет GET-запрос к http://localhost:5140/RevitTask, чтобы забрать новую задачу из очереди.
- Если задача найдена (response.IsSuccessStatusCode), она разбирается в JObject, и достается task.
- Если задача не пуста, передает её в ExecuteTask().
- Если задач нет, ждет 10 секунд (Thread.Sleep(10000)) перед следующим запросом.
- В случае ошибки исключение обрабатывается, и поток снова уходит в ожидание.
Метод ExecuteTask отвечает за выполнение задачи. Здесь можно реализовать экспорт в IFC/NWC, валидацию данных, выгрузку в базу и другие процессы.
Итог
Этот код обеспечивает автоматическое выполнение задач внутри Revit. Команда постоянно мониторит сервер и берет задачи в работу без необходимости ручного вмешательства. Такой подход отлично подходит для автоматизированного экспорта моделей, валидации данных или других процессов, требующих запуска в среде Revit.
Шаг 4: Настройка среды разработки
Для вашего удобства был создан профиль, который позволяет запускать сервер и клиент одновременно. Это даст возможность отлаживать приложение Revit и сервер одновременно.
Удобный доступ до API реализован с помощью Scalar. И с его помощью в данном тестовом проекте появляется возможность добавить задачу в очередь
Шаг 5: Параллельное выполнение на нескольких экземплярах Revit
Теперь давайте перейдем к самой интересной части — выполнению нашей задачи параллельно в нескольких экземплярах Revit. Для этого предварительно в файле appsettings.json необходимо добавить поля, чтобы упростить настройку сервера.
И после создать класс, с помощью которого на серверной стороне мы сможем запускать экземпляры Revit. Данный код позволяет автоматизировано запустить Revit-ы на выполнение нашей задачи в бесконечном цикле. И теперь через API мы можем добавлять сколько угодно задач и они будут параллельно выполняться 3 Revit-ами.
Так же не забываем зарегистрировать наш сервис builder.Services.AddHostedService<RevitBackgroundService>();
Вывод
Теперь у нас появилась возможность пакетно запускать задачи, выполнение которых возможно только в контексте Revit. Это значительно может значительно увеличить производительность труда BIM отдела, ведь появляется возможность подключить уже существующий плагин в эту логику и пакетно обрабатывать большой объем моделей на серверной машине или даже на нескольких машинах одновременно.