Приточная установка на собственной библиотеке в MasterSCADA4D
Приточная установка на собственной библиотеке в MasterSCADA4D

Если вы хоть раз разрабатывали SCADA-интерфейс, то знаете эту боль: унылые стандартные элементы, примитивная графика, дизайн уровня 90-х и никаких особо альтернатив, кроме как использовать свои изображения .png, а в качестве "анимации" использовать скрытие и отображение кучи картинок друг над другом.

Мы решили разработать свою библиотеку элементов для ОВиК. Взяли и "взломали" систему: наняли дизайнеров, отрисовали всё в Figme в SVG, а потом научили эти картинки анимироваться и управляться как родные блоки.

Что не так со стандартными элементами

Стандартные блоки в MasterSCADA4D вполне информативны, но не особо функциональны. Их набор довольно скуден и не гибок. Нет возможности легко адаптировать интерфейс к темной и светлой темам, скрыть ненужные элементы в объекте.

Стандартные элементы ОВиК
Стандартные элементы ОВиК

Мы сделали довольно много объектов и довольно часто слышали просьбы служб эксплуатации изменить стандартное, добавить темную тему, возможность кастомизации, в том числе цветовой.

Приточная установка с резервирование двигателей в MasterSCADA4D
Приточная установка с резервирование двигателей в MasterSCADA4D

Любое нестандартное оборудование, или элементы установки приходилось делать изображениями. Создавали несколько картинок с разным фоном \ цветом индикаторов: в режиме работа, останова, аварии. Затем скрывали ненужные через переменные, описывая в программе на ST логику отображения нужного режима. И так каждый раз. Проблема еще заключалась в том, что в таком решении кастомные объекты были непохожи на стандартные: другой стиль, нет анимации, нет возможности смены цвета (либо снова делать все через множество картинок с поочередным отображением, что при "анимации" давало "рваный" эффект)

"Взлом" стандартных элементов SCADA

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

Через техническую поддержку мы запросили исходники пары стандартных устройств и принялись ковырять их код.

Суть следующая: каждый элемент имеет изображение в формате .svg, в котором все его отрисованные элементы сгруппированы по функциональному назначению (например, по режимам работы) и написан код работы с ними, и файл .xml, в котором описываются все внешние параметры, которые будут управлять элементами в объекте.

Пример группировки элементов в Inkscape
Пример группировки элементов в Inkscape

Пример кода в файле .svg (достаточно открыть файл текстовым редактором)

<defs
     id="defs1" />
  <style
     type="text/css"
     id="style1"><![CDATA[
	 #pump.Alarm #power_off{display:none} 
	 #pump.Alarm #power_on{display:none}
	 #pump.Alarm #mode_visible{display:none}
	 #pump.Alarm #alarm_pmp_on{display:inline}
	 
	 #pump.AlarmSensor #temp_visible{display:none}
	 #pump.AlarmSensor #alarm_temp_on{display:inline}
	 
	 #pump.Start #power_off{display:none} 
	 #pump.Start #power_on{display:inline}
	 #pump.no #temp_visible{display:none} 
	 #pump.noFC #power_visible{display:none}
	 #pump.noFC #power_invisible{display:inline}
	 #pump.noFC #mode_visible{display:none}
	 
	 
	 ]]></style>

А в файле .xml с таким же названием, что и изображение в .svg указываем используемые параметры

<?xml version="1.0" encoding="utf-8"?>
<SvgDef xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" CreateCommonAvary="false">
  <ParameterDefs>
    <ParameterDef Name="Rotation" DisplayName="Вращение" Type="STRING" ParamType="Attribute" ItemId="pump" Path="class">
      <Value DisplayName="Выкл">Stop</Value>
      <Value DisplayName="Вкл">Start</Value>
    </ParameterDef>
    <ParameterDef Name="Alarm" DisplayName="Авария" Type="STRING" ParamType="Attribute" ItemId="pump" Path="class">
      <Value DisplayName="Выкл">noAlarm</Value>
      <Value DisplayName="Вкл">Alarm</Value>
    </ParameterDef>
    <ParameterDef Name="AlarmSensor" DisplayName="Авария датчика" Type="STRING" ParamType="Attribute" ItemId="pump" Path="class">
      <Value DisplayName="Выкл">noAlarmSensor</Value>
      <Value DisplayName="Вкл">AlarmSensor</Value>
    </ParameterDef>
    <ParameterDef Name="Invis" DisplayName="Наличие датчика" Type="STRING" ParamType="Attribute" ItemId="pump" Path="class">
      <Value DisplayName="Нет">no</Value>
      <Value DisplayName="Да">yes</Value>
    </ParameterDef>
    <ParameterDef Name="InvisFC" DisplayName="Наличие ПЧ" Type="STRING" ParamType="Attribute" ItemId="pump" Path="class">
      <Value DisplayName="Нет">noFC</Value>
      <Value DisplayName="Да">yesFC</Value>
    </ParameterDef>
    <ParameterDef DisplayName="Название" Type="STRING" ParamType="Attribute" ItemId="name_text" Path="content" />
    <ParameterDef DisplayName="Статус" Type="STRING" ParamType="Attribute" ItemId="mode_text" Path="content" />
    <ParameterDef DisplayName="Мощность" Type="STRING" ParamType="Attribute" ItemId="power_text" Path="content" />
    <ParameterDef DisplayName="Размерность мощности" Type="STRING" ParamType="Attribute" ItemId="power_postfix_text" Path="content" />
    <ParameterDef DisplayName="Значение датчика" Type="STRING" ParamType="Attribute" ItemId="temp_text" Path="content" />
    <ParameterDef DisplayName="Размерность датчика" Type="STRING" ParamType="Attribute" ItemId="temp_postfix_text" Path="content" />
    <ParameterDef Name="StateWorkColorOn" DisplayName="Цвет состояния Вкл" Type="HMI.SolidColorType" ParamType="Attribute" ItemId="circle2_on" Path="stroke" />
    <ParameterDef Name="StateWorkColorOff" DisplayName="Цвет состояния Выкл" Type="HMI.SolidColorType" ParamType="Attribute" ItemId="circle2_off" Path="stroke" />
  </ParameterDefs>
</SvgDef>

Как на самом деле работает «взлом»: разбор на живом примере насоса

Возьмем за основу реальный файл насоса, который мы сделали для своей библиотеки. В нем есть:

  • индикация работы/останова с анимированным вращением;

  • авария (моргающая красная рамка);

  • отображение мощности в процентах (или текст «ВЫКЛ»);

  • опциональный датчик температуры;

  • два режима отображения: с частотным преобразователем (ПЧ) и без него.

Структура SVG: группировка по состояниям

Внутри файла pump.svg все элементы сгруппированы в теги <g> с понятными id:

  • power_on – вращающаяся синяя дуга (двигатель работает)

  • power_off – статичная залитая дуга (двигатель остановлен)

  • alarm_pmp_on – мигающая красная рамка и текст «АВАРИЯ»

  • power_visible / power_invisible – показывают либо число (100 %), либо слово «ВЫКЛ»

  • temp_visible / alarm_temp_on – нормальный или аварийный режим датчика

  • mode_visible – текстовый статус (например, «ВЫКЛ»)

Важное правило: в SVG нельзя просто взять и спрятать группу через display:none – это не сработает. Мы используем каскадные CSS-правила, которые написаны внутри тега <style> в начале файла.

Вот пример из кода:

#pump.Alarm #power_off{display:none} 
#pump.Alarm #power_on{display:none}
#pump.Alarm #mode_visible{display:none}
#pump.Alarm #alarm_pmp_on{display:inline}

Если у корневого элемента с id="pump" есть класс Alarm, то:

  • спрятать группу power_off

  • спрятать группу power_on

  • спрятать mode_visible

  • показать alarm_pmp_on

Таким образом, переключая класс у корневого тега <g>, мы изменяем отображение целых блоков графики, чистая магия CSS + SVG.

Как SCADA управляет этими классами

В комплекте с SVG идет XML-файл с расширением .xml. В нём описано, какие параметры из проекта MasterSCADA4D за что отвечают.

Например:

  • Name="Alarm" – имя переменной внутри SCADA, которую вы привяжете к тегу (биту аварии).

  • ItemId="pump" – какой элемент SVG мы меняем (наш корневой <g id="pump">).

  • Path="class" – мы будем изменять атрибут class этого элемента.

  • Значения: если переменная Alarm = "Выкл", класс становится noAlarm; если "Вкл" – класс становится Alarm. А в SVG уже есть правила, что делать при появлении класса Alarm (см. CSS выше).

Аналогично сделано для:

  • Rotation – переключает классы Stop / Start (вращение анимации)

  • InvisFC – переключает классы noFC / yesFC (скрывает или показывает текст «100%»)

  • AlarmSensor – отвечает за аварию датчика температуры

Анимация без скриптов

Вращение двигателя сделано через SVG-анимацию:

<animateTransform
   attributeName="transform"
   type="rotate"
   from="0 107.44529 130.13976"
   to="360 107.44529 130.13976"
   dur="2s"
   repeatDur="indefinite" />

Этот код вращает синюю дугу вокруг центра насоса. Анимация встроена прямо в группу power_on. Пока группа скрыта (класс Stop) – вращения нет. Как только SCADA присваивает класс Start – дуга появляется и начинает крутиться.

Аварийное мигание сделано через animate для прозрачности:

<animate
   attributeName="opacity"
   dur="1s"
   values="0.2;0.8;0.2"
   repeatCount="indefinite" />

Динамический текст и единицы измерения

В параметрах XML вы можете привязать любой текст внутри SVG:

<ParameterDef DisplayName="Мощность" Type="STRING" ParamType="Attribute" ItemId="power_text" Path="content" />

ItemId="power_text" – это идентификатор текстового элемента внутри SVG.
Path="content" – значит, SCADA будет заменять содержимое этого текстового узла (то, что между <text>...</text>).

Точно так же можно менять цвет обводки или заливки:

<ParameterDef Name="StateWorkColorOn" DisplayName="Цвет состояния Вкл" Type="HMI.SolidColorType" ParamType="Attribute" ItemId="circle2_on" Path="stroke" />

Это позволяет пользователю прямо в редакторе SCADA выбрать цвет работающего двигателя – без правки SVG.

Стоит учесть

  • Имена классов в CSS должны совпадать со значениями в XML (<Value DisplayName="...">Точно_такое_же_имя_класса</Value>).

  • Корневой элемент SVG (обычно <g id="myDevice">) должен иметь атрибут class, который SCADA будет менять.

  • Если вы хотите динамически менять цвет – используйте атрибуты stroke или fill, а не CSS-классы.

  • Анимации (animateanimateTransform) работают только когда группа видима. Это экономит ресурсы.

После сохранения в среде разработки MasterSCADA4D добавляем объект, создаем окно, нажимаем на окно в дереве проекта правой кнопкой и Импорт SVG, после чего появится окно предпросмотра с привязкой параметров.

Окно подтверждения импорта нового объекта из SVG
Окно подтверждения импорта нового объекта из SVG

После подтверждения можно использовать наш собственный элемент в проекте со всеми его прописанными свойствами и анимациями.

Параметры элемента в MasterSCADA4D
Параметры элемента в MasterSCADA4D

Как это собрать воедино

  1. Рисуете в Figma или Inkscape все состояния элемента, группируете их с понятными id.

  2. Открываете SVG в текстовом редакторе, добавляете блок <style> с CSS-правилами включения/выключения групп по классам.

  3. Создаёте XML с описанием параметров: для каждого переключателя (авария, работа, наличие датчика) указываете, какой id и какой атрибут (classcontentstroke) менять.

  4. В MasterSCADA4D через меню «Импорт SVG» выбираете оба файла. Среда сама подхватит параметры из XML и предложит их привязать к тегам проекта.

Ссылка на исходники собственного элемента в данном примере будет в конце статьи

Разработка собственной библиотеки элементов в MasterSCADA4D

Инженеры творят могущество, но именно художники спасают мир от топорности.

Собрались, покопались в примерах, поняли как нужно и начали искать дизайнеров. Дизайнеры знают как будет красиво, но не понимают как это оборудование работает и какую индикацию нужно отображать, поэтому совместными усилиями начали прорабатывать варианты в Figma.

Пример водяного нагревателя в Figma
Пример водяного нагревателя в Figma

Составили Техническое задание, показали на живом оборудовании как это выглядит, обсудили как это должно выглядеть в SVG и приступили к работе. Вариантов было много...

Пример парового увлажнителя в Figma
Пример парового увлажнителя в Figma

Для каждого элемента было сделано несколько разных вариантов.

Огромная благодарность за терпимость и понимание чутких творцов

Переключатели в Figma
Переключатели в Figma

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

Наборы установок в Figma
Наборы установок в Figma
Больше фото
Проработка аварийных индикаторов
Проработка аварийных индикаторов
Отображение элементов в светлой теме
Отображение элементов в светлой теме
Аварии по всем элементам
Аварии по всем элементам
В остановленном состоянии
В остановленном состоянии
В работе
В работе
Без верхних и нижних подписей
Без верхних и нижних подписей
На разном светлом фоне
На разном светлом фоне
Подбор размеров при сложных установках
Подбор размеров при сложных установках

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

Главный экран АРМ Диспетчера на одном из объектов в темной теме
Главный экран АРМ Диспетчера на одном из объектов в темной теме
Очень много скринов
Приточная установка в темной теме
Приточная установка в темной теме
Вытяжные установки в темной теме
Вытяжные установки в темной теме
Дренажные приямки
Дренажные приямки
Статусы ВРУ и анализаторы сети
Статусы ВРУ и анализаторы сети
Тепловые завесы и кондиционеры
Тепловые завесы и кондиционеры
Таблица связи с устройствами
Таблица связи с устройствами
Журнал событий
Журнал событий
Журнал активных аварий
Журнал активных аварий
Окно настроек
Окно настроек
Окно настроек в светлой теме
Окно настроек в светлой теме
Скрытие блоков у элементов
Скрытие блоков у элементов
Главное окно
Главное окно
Приточная установка
Приточная установка
Приточная установка со скрытыми подписями
Приточная установка со скрытыми подписями
Вытяжки
Вытяжки

Скачать ПРИМЕР из статьи.

Всем красивых и информативных интерфейсов, а мы пошли дальше отрисовывать ОВиК.

Telegram канал

Комментарии (14)


  1. NovoselovAG
    27.05.2026 17:38

    Это за документированная возможность создания собственных элементов палитры. Даже видеоурок есть. От чего же такое название у публикации, про взлом?


    1. CYNTRON Автор
      27.05.2026 17:38

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


    1. CYNTRON Автор
      27.05.2026 17:38

      Касательно документации - судя по ее тексту она и была (скорее всего) сделана на основе нашего поста в ТГ по круглому элементу из примера с год назад.


      1. NovoselovAG
        27.05.2026 17:38

        Ролик на ютубе появился 3 года назад а сама документация ранее. Пользовались ей при разработке проекта в 2022 году


  1. roman_grach
    27.05.2026 17:38

    А как вывести число с заданными количеством знаков после запятой в текстовом атрибуте?


    1. CYNTRON Автор
      27.05.2026 17:38

      Мы сделали через программу в объекте. Там же добавили возможность выводить корректные значения при входных типа int и типа real.


      1. roman_grach
        27.05.2026 17:38

        Ещё есть штатная возможность при редактировании связи задать формат значения. Увидел после того, как попытался поэкспериментировать с вашим компонентом. Это конечно не так удобно, как при использовании стандартных компонентов, но ради эстетики можно потерпеть.

        И да, забыл сказать: спасибо большое, что делитесь информацией!


  1. ellusive3
    27.05.2026 17:38

    Смысл примитивных интерфейсов в их информативности и легком считывании необходимых показателей. Все эти свистоперделки с тенями, крутыми анимациями и т.д. только усложняют работу с системой. Это не сайт, чтобы наряжать его, а мнемосхема объекта и в критический момент нужно определить проблему и среагировать


    1. CYNTRON Автор
      27.05.2026 17:38

      На вкус и цвет все фломастеры одинаковые.

      Как в стандартных элементах отличить одну аварию от другой, если там всего один параметр аварии?

      Или как в стандартных элементах отобразить переходный процесс, которого там не предусмотрено?

      И я могу так долго продолжать.


  1. EXEparadoxxx
    27.05.2026 17:38

    Так и не понял, в чем заключался "взломали" и "заставили работать на svg", если это штатный функционал данной SCADA, которым многие разработчики вполне успешно пользуются. Да и примеры работы с динамическими svg как минимум пару лет присутствуют в документации.


    1. CYNTRON Автор
      27.05.2026 17:38

      Взломали - потому что из документации в то время было всего пару строк.

      Штатный - да, но на тот момент нормально не описаный.

      Пару лет - текст справки сравните с примером выложенным. Этот элемент у нас в ТГ канале как раз пару лет назад и был, а справка очень похожа на описание именно его. Совпадение.


  1. Tommy_M
    27.05.2026 17:38

    Красиво, но внезапный Times New Roman везде портит старания дизайнера.


    1. CYNTRON Автор
      27.05.2026 17:38

      Мы еще поработаем над этим)


      1. NovoselovAG
        27.05.2026 17:38

        "Взломаете" Times New Roman ?