Что же такое переносимое программное обеспечение? Это такие программы, которые не зависят от платформы: как аппаратной, так и программной. Чтобы обеспечить переносимость, необходима стандартизация интерфейсов, в том числе внутри самих программных компонентов, а также на уровне взаимодействия с операционной системой, внешними службами и протоколами.
Для этого важна модульная архитектура при проектировании ПО. Функциональность должна быть разделена на независимые компоненты, которые могут обновляться и заменяться отдельно. Это улучшает и переносимость, и взаимозаменяемость компонентов, а также их поддержку. С точки зрения поддержки и бизнес-требований, переносимое ПО помогает снижать затраты на разработку. Также оно обеспечивает защиту инвестиций, продлевая жизненный цикл программных продуктов, в том числе при модернизации оборудования, что особенно важно в промышленной автоматизации.
Говоря о повышении конкурентоспособности: обеспечив переносимость ПО, мы можем не зависеть от конкретного поставщика оборудования и выбирать максимально оптимальные решения для различных программных компонентов.
Бизнес-требования для переносимого ПО предполагают постоянную эволюцию технологий: развитие аппаратных платформ, появление новых процессоров, электроники и компонентов полевой части промышленной автоматики. Всё это требует адаптации существующего ПО. Если ПО построено качественно и обеспечивает лёгкую адаптацию, мы получаем огромное преимущество с точки зрения бизнес-требований.
Также бизнес-требования касаются интеграции гетерогенных систем - стандартная ситуация, когда современные предприятия используют оборудование различных производителей. Это обеспечивает технологическую независимость и снижает зависимость от зарубежных поставщиков. И это ключевая цель импортозамещения, особенно учитывая геополитическую нестабильность. Промышленная автоматика тесно связана с критической инфраструктурой, поэтому это требование является ключевым при проектировании промышленного ПО.
Можно сузить предметную область до ПО в промышленной автоматизации, точнее - в АСУТП, то есть алгоритмов технологических процессов. Это промышленная автоматика, которая работает по циклу, чаще всего без прямого участия оператора. Нас интересуют только первые два уровня АСУТП - полевой и контроллерный. Классическая градация уровней автоматизированной системы управления технологическими процессами включает полевой уровень, контроллерный уровень и диспетчерский. Последний, связанный с HMI, SCADA, MES и прочими, не так интересны.
Немного о терминах. Существует распространённое деление на IT-мир и OT - Information Technologies и Operational Technologies. Первый - это фактически всё, что связано с ПО, второй - управление процессами. Промышленная автоматизация относится к миру OT. IT развивается очень быстро, особенно технологии интернета вещей, виртуализации и облачных сервисов пытаются войти в мир OT. Но главная задача OT - минимизировать простой на предприятии. Это главный источник различий требований к ПО OT.
Из этого вытекают требования: детерминированность, резервирование, ограничение на сценарии обслуживания и обновления ПО.
Есть стандарты для универсального программирования ПЛК - IEC 61131 и IEC 61499. Они существуют уже много лет, позволяют с низким порогом обучать специалистов АСУТП. Но контроллерное ПО всегда связано с аппаратным обеспечением, вводом-выводом, и проектирование требует серьёзных решений по абстракции аппаратного уровня, поэтому без этой абстракции переносимость невозможна.Фактически получились закрытые проприетарные решения. На рынке сформировалось несколько крупных закрытых экосистем - например, Siemens, Schneider, Emerson. В крупных проектах, как правило, выхода нет - приходится использовать решения одного вендора.
IEC 61131 и IEC 61499 - это стандарты для ПЛК, которые описывают языки программирования и архитектуру ПО. IEC 61131 определяет формат проекта (XML), позволяющий перемещать проекты между устройствами разных производителей. IEC 61499, в свою очередь, развивает идеи IEC 61131, усложняет архитектуру проекта, предусматривая функциональные блоки, которые могут перемещаться между контроллерами, управляться с помощью событий и передачи данных.
Для реализации стандартов на программно-аппаратном комплексе нужны: среда исполнения на контроллере и среда разработки для проектирования, загрузки, отладки и обслуживания проектов АСУТП.
Поскольку мы говорим о промавтоматике, переносимый код нельзя писать на популярных платформах Java или .NET. Рассмотрим ОС с ядром Linux, убирая Windows (неинтересна с точки зрения импортозамещения и федеральных законов).
Итак, есть хороший структурированный адаптируемый код. Но ПО, собранное из него, имеет зависимости: от системных библиотек ОС, прежде всего libc. При смене версии ОС меняется реализация libc - ПО перестаёт запускаться, возникают конфликты. Есть зависимости от служб и Middleware, прежде всего от сети и сетевых протоколов. Контроллеры и подсистемы ввода-вывода вносят значительные зависимости. Также существует множество системных настроек, от которых зависит любая среда исполнения на контроллере.
Что же делать?
Первое, что приходит из мира IT - контейнеризация. Современные контроллеры на Linux поддерживают контейнеризацию, а отечественные зрелые ОС давно имеют её. Но контейнеризация увеличивает требования к ресурсам и не решает всех проблем, особенно с вводом-выводом. Ввод-вывод внутри контейнера требует множества манипуляций с правами доступа, и выгода от контейнеризации снижается.
Второй вариант - сборка ПО: если код переносимый, адаптируем его под контроллер. Берём зрелый контроллер под Linux. Обычно это не стандартная отечественная ОС, а собственная сборка производителя (например, OpenWRT у Овен, Ubuntu или сборки на базе Buildroot у других). Можно адаптироваться под это. Есть Runtime, полностью реализующий стандарт IEC 61131 или 61499, есть функциональные блоки для ввода-вывода. Чтобы собрать код на C, нужно учесть все зависимости ОС. Хотя можно собрать модульно и без зависимостей, чаще это сложно.
Пример: проект с открытым исходным кодом Zenoh — среда обмена сообщениями, хранения настроек для промышленной автоматизации и роботизации. Он написан на Rust, и в релизах есть сборки под разные ОС: Apple Darwin, Linux (различные версии libc, включая embedded вариант musl).