Я, как любой другой любитель «поковыряться» в различных железках, связанных с датчиками, микроконтроллерами и сопутствующих штуках, несколько лет назад столкнулся с необходимостью связать очередную микроконтроллерную историю с ПК, а именно, мне нужно было выводить в реальном времени значения различных сигналов с МК на дисплей компьютера в виде различных графиков, прогресс‑баров, а также, с помощью кнопок и ползунков управлять моим «железом».

В тот момент я уже относительно продолжительное количество времени работал на должности «инженер АСУ ТП», поэтому не понаслышке знал о популярных существующих системах диспетчеризации (по другому — SCADA системах) и для моих целей этого было крайне избыточно, особенно если учитывать их физический объем на жестком диске, необходимость использования OPC‑сервера и/или специфичных протоколов обмена.

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

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

Кратко, что такое SCADA-система

Случайный пример реализации SCADA, который я нашел в интернете
Случайный пример реализации SCADA, который я нашел в интернете

SCADA (Supervisory Control And Data Acquisition — диспетчерское управление и сбор данных) — программный пакет, предназначенный для разработки или обеспечения работы в реальном времени систем сбора, обработки, отображения и архивирования информации об объекте мониторинга или управления. (взято тут)

Более подробное описание того что это такое можно с легкостью найти на просторах интернета, я лишь хотел сразу обозначить, что, под термином «SCADA», часто имеют в виду весь комплекс от контроллеров и различных датчиков до HMI (человеко‑машинный интерфейс — то самое, что мы видим на дисплее компьютера и жмакаем по различным кнопкам). В пределах данной статьи разговор будет идти именно о HMI, что тоже покрывается термином «SCADA», особенно, на реальных объектах в разговорной речи.

ASCADA. Что это такое и почему я её называю "простейшей".

ASCADA — это программа, основанная на C# Winforms (.Net 3.5 для большей совместимости, чтобы на каждом "тапочке" работала без проблем). Предназначена для быстрого и простого проектирования систем визуального контроля технологических параметров, передаваемых от микроконтроллеров через последовательный порт или промышленных контроллеров через протоколы Modbus RTU/TCP. Используется в домашних решениях для управления и отображения различных параметров.

С первого взгляда видно то, что это сделано на Winforms, о чем сейчас сожалею, так как почти 90% времени работаю с линуксом, а там, через wine это дело работает мягко говоря кривовато (но работает), да и по "красивости" интерфейса есть вопросы, но да ладно.

Общий принцип такой: внутри проекта создаются так называемые теги - так в АСУ ТП называют различные сигналы, или более привычно - переменные. Теги, как и переменные, могут быть разных типов, в моем варианте предусмотрены следующие типы: bool, int, float, string. Здесь важно понимать, что тег - это не совсем переменная в привычном смысле, поэтому его тип это почти условность, которая определяет его предназначение.

Пример созданных тегов в ASCADA
Пример созданных тегов в ASCADA

Например:

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

float - это числа с плавающей точкой, следовательно, вы успешно можете привязать его к прогресс-бару, но не получится привязать к этому типу позицию x:y объекта.

string используется в текстовых окнах, чтобы отображать какие либо сообщения от микроконтроллера в текстовом виде.

bool - это тот же int, с той лишь разницей, что используется в дискретных объектах - кнопках, переключателях и т.д. и оперирует со значениями 0 либо 1.

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

Как передавать значения тегов от микроконтроллера в ASCADA

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

0&100*

В этом примере пакета данных мы передали int или float значение 100 в тег с ID равным 0, где & - символ-разделитель, а * - символ конца пакета данных.

Еще несколько примеров: 19&Hello World* - передали строковое значение Hello World тегу с ID =19; 234&1958,59* - передали значение с плавающей точкой 1958,59 в тег ID =234. Как видите, все максимально просто и понятно.

Как выглядит процесс привязки тега к объекту в ASCADA
Как выглядит процесс привязки тега к объекту в ASCADA

На примере с изображения видно что если кликнуть по объекту, то в внизу экрана в поле "Object Tag Property" отображается список из заранее созданных тегов и групп, в которых они были созданы. Также, всегда указывается какие типы тегов выбранный объект поддерживает.

Как "запустить/воспроизвести" созданный проект в ASCADA?

На момент публикации реализовано только два способа запуска созданного проекта:

  • Из менеджера проекта.

  • Путем генерации иконки быстрого запуска.

Первый способ заключается в том, что при сохранении изменений в проекте создается файл с расширением .ascproj, который по своей сути это бинарная сериализация всего и вся что есть в проекте, включая изображения и т.д. Следовательно, если вы сохраните проект в директории программы в папке /Projects, то он отобразится в менеджере проектов, который запускается при старте программы:

Как выглядит менеджер проектов в ASCADA. Это первое что вы увидите при запуске программы ASCADA
Как выглядит менеджер проектов в ASCADA. Это первое что вы увидите при запуске программы ASCADA

Здесь мы кликаем по нужному проекту и видим его превью в виде того что в нем находится и текстовое описание (если мы, конечно, создавали это описание). Далее, у нас есть выбор - запустить его или редактировать, мы нажимаем запустить - кнопку START. После этого в новом окне откроется проект уже не в редакторе, а в виде программы, которая разворачивается на весь экран. Нам остается лишь открыть нужный COM-порт на нужном бодрейте, и, если в этот момент наш микроконтроллер или радиомодем шлет туда пакеты в приведенном выше формате, наши объекты начнут шевелиться, изменять свои значения и т.д.

Пример того куда нужно ткнуть чтобы отрыть необходимый COM-порт для запуска обмена
Пример того куда нужно ткнуть чтобы отрыть необходимый COM-порт для запуска обмена

"Но ведь это долго и неудобно" - скажете вы. И будете правы. Именно поэтому я сделал второй способ запуска - генерация иконки быстрого запуска.

Для этого при редактировании проекта необходимо перейти в его свойства (иконка шестеренки в правом верхнем углу редактора или в Project/Properties).

Свойства проекта в ASCADA
Свойства проекта в ASCADA

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

Стоит лишь выбрать в каком месте на компьютере создать иконку и дать ей имя. Как только мы нажмем Accept, то по указанному пути создастся иконка приложения, при нажатии по которой, наш проект сразу запустится, и, при необходимости, откроет нужный COM-порт!

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

Возможности ASCADA

Для реализации наших проектов в нашем арсенале есть несколько типов объектов, это:

  • Динамические объекты

  • Статические объекты

  • Компоненты

  • Фейсплэйты

Тулбар с объектами, доступными для использования в проекте ASCADA
Тулбар с объектами, доступными для использования в проекте ASCADA

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

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

Компоненты - объекты, которые работают в фоновом режиме, например: звуковой сигнал, который реагирует на значение "1" тега с типом bool и воспроизводит мелодию выбранную на компьютере, CSV-логгер, который с заданным периодом времени пишет значение тега в .csv таблицу и создает тем самым лог, и компонент изменения свойств объекта, который позволяет к свойству какого-либо объекта привязать тег (например положение/размер объекта).

Фейсплэйты - это объекты, которые представляют собой кастомные объекты, созданные из стандартных. Например, мы хотим сделать меню проекта с кнопками навигации по проекту, и, чтобы нам не пришлось каждый раз копировать одни и те же кнопки с экрана на экран - мы создаем один фейсплэйт с ними и вставляем готовый фейсплэйт туда куда нам необходимо. Удобно, согласитесь?:)

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

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

Пример реализаций круглых баров в ASCADA. Слева встроенной векторной графикой, посередине и справа с использованием .png с фотостоков
Пример реализаций круглых баров в ASCADA. Слева встроенной векторной графикой, посередине и справа с использованием .png с фотостоков

Как видите, при желании, можно создать очень даже симпатичный графический интерфейс для своих проектов по диспетчеризации.

Также, хочется отдельно упомянуть возможности самих «экранов» на которых находятся объекты. У экранов тоже есть несколько свойств — вы можете задавать им разрешение, задавать фоновый цвет или выбрать изображение для фона.

Пример использования изображения как фон экрана в ASCADA
Пример использования изображения как фон экрана в ASCADA

Также, есть очень интересная функция — использовать экран как темплэйт. Это означает что выбранный экран можно использовать как «шаблон» для всех других, а именно — все объекты что есть на этом экране, будут отображаться на остальных. Зачем это нужно? А для того, что если вам в вашем проекте, опять же, нужно меню с навигацией или панель с отображением даты и времени, то при реализации темплэйта вам не придется это все создавать/копировать на другие экраны. Как по мне, это удобно:)

А еще, хотелось бы упомянуть что в «плеере проекта», то есть когда проект уже запущен, есть возможность просматривать значения тегов в реальном времени в специальном окне, плюс есть эмулятор в котором вы можете текстом набрать пакет, который ожидаете от микроконтроллера и смотреть как на это реагируют различные объекты — что тоже удобно, чтобы каждый раз не подключать устройство.

Эпилог

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

Как выглядит примитивный пример как отправить в тег ASCADA с ID 4 значение float 36.6 от Arduino:

void send()
{
  float temper = 36.6F;
  String data_pack = "4&" + String(temper) + "*";
  Serial.print(data_pack);
}

На мой взгляд это максимально просто, что справится даже самый начинающий.

Не буду в подробностях описывать другие возможности ASCADA в данной статье, как например, возможность работы через протоколы Modbus RTU и Modbus TCP, так как не вижу смысла. Если кого-то это интересует, то этот человек и сам разберется с интерфейсом.

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

Даже больше, если будет какая то обратная связь и данный проект кого-то заинтересует, то я открою исходники в общий доступ для возможного развития - мне абсолютно не жалко:) Но скажу сразу, что в тот момент я только начинал изучать C# и создание графических приложений как таковых, а значит, данный софт просто весь состоит из костылей и неправильных решений. Спустя столько лет я бы все делал абсолютно по другому, с нормальной архитектурой и т.д. Но что есть, то есть :)

Буду рад критике, как мы знаем, без нее не бывает развития. А еще больше, если кому то было интересно!

Делюсь ссылкой на гитхаб уже скомпиллированного проекта, который нужно только запустить и пользоваться. Всем добра!

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


  1. zatim
    22.10.2023 12:44
    +1

    Я правильно понимаю, при передаче значения переменной ее тип не передается? Как программа угадывает его тип? Как отличает целочисленную 5 от строковой '5', например?


    1. MikeKozlovAVR Автор
      22.10.2023 12:44
      +1

      Этот нюанс лежит на стороне разработчика со стороны МК, ведь тип тега определяет то как он будет парситься в ASCADA. Ведь так или иначе значение отсылается в символьном виде. Ну а вообще, вопрос вполне справедливый, мне на тот момент показалось удачной идея написать библиотеку для МК внутренностями которой и будет проверяться корректность значения


      1. zatim
        22.10.2023 12:44

        Мы, видимо, о разных вещах говорим. Ведь ascada и запускается на пк, она ведь и должна парсить входные данные от мк, разве нет? Или, по вашей задумке, данные будут ходить строго от пк к мк?

        мне на тот момент показалось удачной идея написать библиотеку для МК внутренностями которой и будет проверяться корректность значения

        А разве не проще добавить в тег всего один символ - букву, обозначающую тип. I, F, B, S, например. Это полностью исключит разночтения и существенно упростит парсинг.


        1. kmarakov
          22.10.2023 12:44

          Венгерская нотация?


    1. SpiderEkb
      22.10.2023 12:44
      +2

      На самом деле, каждая переменная (тег) - это текущее значение какого-то датчика. И тип этого значения определяется уже на уровне визуализации исходя из того, что это за датчик.

      Специфика в том, что значение датчика может быть физически типа bool ("нормальное стояние" / "аварийное состояние"), а отображаемая переменная при этом будет иметь тип string - расшифровка того, что там не самом деле произошло.


      1. zatim
        22.10.2023 12:44

        А, понял, тип прописывается заранее, согласно номеру ID. Спасибо за разъяснение)


        1. SpiderEkb
          22.10.2023 12:44
          +1

          Я не утверждаю что здесь именно так. Но тег - это не типизированная переменная. Это просто идентификатор какого-то датчика. Как трактовать его показания - это уже вопрос конфигурации системы на стороне ПК.


    1. MiraclePtr
      22.10.2023 12:44
      +2

      Я так понимаю, программа уже знает, какого типа какой тег, ещё на этапе конфигурации (привязок данных).

      Точно так же как, например, при использовании классического Modbus RTU/TCP в любой классической скаде (точнее, в OPC-сервере) при считывании данных с устройства вы не можете определить, что именно лежит в регистре - signed int, unsigned int, часть signed long/unsigned long/float (и какой порядок байт endianness у устройства?) или вообще набор битовых флагов. Пожтом вы задание тип данных для тега при создании тега в программе


  1. SpiderEkb
    22.10.2023 12:44

    Как выглядит примитивный пример как отправить в тег ASCADA с ID 4 значение float 36.6 от Arduino

    Не совсем понятно - связь тега с конкретным датчиком захардкожена в прошивке контроллера?


    1. MikeKozlovAVR Автор
      22.10.2023 12:44

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


      1. SpiderEkb
        22.10.2023 12:44

        Хорошо. Допустим, у вам на порту 1 висит какой-то датчик.

        По ряду причин, вам потребовалось его перевесить на порт 2.

        Потребует это правки кода на МК?

        Аналогично - есть датчик на порту . Вешаем еще один на порт 2. Нужно править код на МК?

        Или в вашем случае "тег" связан с физическим портом на МК (и МК передает фактически значени того, что там на порту висит), а разборки что там это значит уже на стороне ПК идут?


        1. MikeKozlovAVR Автор
          22.10.2023 12:44

          Нет, тег никак не связан с портом. То есть внутри ASCADA реализован парсинг всего что прилетает в порт, и уже в зависимости от того что именно пришло происходит событие которое изменяет значение в привязанных к конкретному тега объектах


          1. SpiderEkb
            22.10.2023 12:44
            +3

            при подключении нового устройства требуется изменение кода МК?

            Почему спрашиваю. В свое время занимался подобным. Делали "систему мониторинга инженерного оборудования зданий". МК там свои были, на STM32. Визуализация тоже своя - карта обслуживаемого района с объектами, окно аварийных сообщений...

            Но там было требование - любые изменения конфигурации должны быть "на горячую, без остановки системы" (просто потому что остановить систему ЛДСС - лифтовая диспетчествкая связи и сигнализация - по нормативам означает предварительное отключение всх лифтов. А их в системе может быть 300-500 штук...)

            Посему, у нас была разработана классификация устройств. Например, для датчика типа "сухой контакт" было так:

            • Тип датчика (информационный, аварийный, триггер, с задержкой)

            • Нормальное состояние (замкнут/разомкнут) - для всех, кроме информационных

            • Задержка (для датчиков с задержкой)

            Тип датчика:

            • информационный - не генерирует событий, только возврат состояния по запросу

            • аварийный - обычный датчик, который генерирует событие при переходе из нормального состояния в аварийное.

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

            • с задержкой - аварией считается не одиночный переход в аварийное состояние, но непрерывное нахождение в нем в течении заданного времени

            Устройства подключаются к контроллеру нижнего уровня (УСО - устройство сопряжения с объектом). При старте УСО запрашивает у системы карту своих устройств и хранит ее в памяти в виде номер клеммы (куда подключено устройство), тип устройства, блок конфигурации (если нужно). Есть команды "удалить устройство из карты" и "добавить устройство в карту".

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

            УСО постоянно "обтряхивает" состояние устройств по карте конфигурации. Обнаружило повод для события (например, переход из нормального состояния авариное) - посылает наверх (на контроллер верхнего уровня - IP-шлюз) короткое сообщение - номер клеммы + состояние.
            IP-шлюз добавляет к посылке номер УСО (их несколько, может быть и 10 и 20 и 30 на одном шлюзе) от которого пришло сообщение и отправляет на комп в диспетчерской. Там дописывается номер шлюза и это идет в обработку - номер шлюза+номер УСО + номер клеммы составляют "физический адрес устройства в системе". Дальше блок данных (в общем случае).

            Система уже по адресу устройства в таблице определяет что это такое и как нужно обрабатывать данные. Например, для аварийного датчика будет прописано аварийное сообщение - что на самом деле есть "переход в аварийное состояние".

            Кроме того, устройство привязано к объекту - где оно установлено. В результате, получив, скажем посылку 01 03 02 01 система раскрутит ее как:

            • IP-шлюз 1

            • УСО 3

            • Клемма 2

            • Состояние 1

            Дальше по таблице - это охранная сигнализация машинного помещения пассажирского лифта, улица .... дом ... подъезд ... Состояние 1 означает "несанкционированное проникновение". На основе всего этого будет сформировано понятное человеку сообщение, еще и на карте будет подсвечено где именно случилось.

            Это так, вкратце. В реале там всего кратно больше и сложнее, но в общем и целом принцип такой.


            1. MikeKozlovAVR Автор
              22.10.2023 12:44
              +1

              Всё, я понял что вы имели в виду. Смотрите, если конкретная реализация кода на микроконтроллере позволяет на ходу добавлять/удалять какой либо сигнал из системы не останавливая ее - то есть не хардкодом, а конфигурацией то да, так сделать можно. Ведь данный софт не прикладной всё таки, а скорее как конструктор системы. Но в самой ASCADA на горячую изменить тег не получится, придется перезапускать HMI-проект. Как возможный вариант - это зарезервировать заранее в проекте какое нибудь количество тегов и добавлять удалять сигналы путем создания отдельного экрана с текстовыми/числовыми полями и кнопками из разряда: поле номер клеммы, поле ID тега, поле имя сигнала, кнопка добавить/удалить. Но всю механику этих процессов всё равно нужно будет предусматривать в ПО на микроконтроллере.


              1. olku
                22.10.2023 12:44

                А можно плагинами сделать? Поллим папку с сериализованными объектами тегов, далее load/unload. Для безопасности и совместимости плагины можно подписывать... и продавать.


                1. MikeKozlovAVR Автор
                  22.10.2023 12:44

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


  1. agalakhov
    22.10.2023 12:44
    +1

    Почему в качестве разделителя выбран такой странный символ, &? Чем хуже, например, 0=42.0 1=21.7 ?


    1. MikeKozlovAVR Автор
      22.10.2023 12:44

      Если честно, уже и не помню причину, вроде бы связано было с передачей string в которой мне нужен был символ '=', а '&' не использовался вообще нигде


  1. smart_pic
    22.10.2023 12:44

    Как передать значение переменной из МК в систему понятно.

    А как передается значение при изменении свича или слайдера в системе в МК.?

    формат сообщений одинаковый?


    1. MikeKozlovAVR Автор
      22.10.2023 12:44

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


  1. igorts
    22.10.2023 12:44
    +2

    Изначально SCADA пакет создавались под Unix системы, помню такой SCADA пакет RTAP/Plus от компании Hewlett-Packard, который функционировал по ОС HP-UX, и эти системы были дорогими и доступными только для больших компаний

    Потом в какой то момент появились реализации под Windows (один из первых был пакет Intouch) и в силу низкой стоимости и популярности intel+Windows эти пакеты практически вытеснили юниксовый

    Затем появился протокол OPC DA , который стал стандартом де факто для SCADA и который основан на протоколе сетевого взаимодействия от MS - DCOM, что надолго привязало SCADA пакеты к платформе Windows (думается MS тут немало пстарались)

    Наконец после популяризации Linux и появления спецификации протокола OPC UA, основанного на TCP или HTTPS картина стала постепенно меняться, появилось много решений под Linux

    Тенденция сейчас все больше к созданию гуи под Web технологии, наиболее часто встречается связка svg, http, js на платформе которых и делают пользовательский интерфейс


    1. MikeKozlovAVR Автор
      22.10.2023 12:44

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


      1. olku
        22.10.2023 12:44
        +1

        JavaFX кроссплатформенна, есть редактор форм.


    1. ponikrf
      22.10.2023 12:44
      +3

      По сути так и есть - это решение из прошлого века.

      Я даже больше скажу, когда мы заменили скаду на собственное решение с использованием Grafana получилось в итоге даже лучше. Потому что смотреть на цифры в один момент времени не имеет большого смысла. Графики показывают полноценно работу системы, и по ним можно полноценно диагностировать проблемы.

      Ну и в целом SCADA в том виде в котором она была - имеет ну слишком много проблем. Рассказ об этом на самом деле тянет на целую статью.


      1. SpiderEkb
        22.10.2023 12:44
        +1

        Ну вот мы сразу собственное решение двигали. Но... Начиналось это в 1993-м году (первые мк делали на 8080) и про скаду никто тут не слышал еще.

        Вообще все с нуля делали, аналогов в стране не было.

        Ну а аотом уже не было смысла на скаду уходить - слишком много наработок было.

        Окончательная версия - двухуровневая сеть мк (между собой они по rs485 общались, с сервером по udp), сервер ("ядро") к которому с одной стороны подключались мк верхнего уровня, с другой - интерфейсные клиенты разного плана (диспетчер, аварийная бригада, еще что-то).

        Все это сильно распределенное было и достаточно объемное


        1. igorts
          22.10.2023 12:44

          Мы делали сами систему сбора данных, разные протоколы, под разные SCADA и на текущий момент практически во всех проектах ее используем

          Делали и SCADA , но не стали ее развивать, слишком это дорого, не окупится


          1. SpiderEkb
            22.10.2023 12:44

            У нас оно было специализированное - то, что на диспетчерских в УК работает. Соответственно, интерфейс был сразу заточен на "неквалифицированного пользователя" - максимально просто и наглядно показывать что и где случилось.

            Основная специфика там была в том, что все это очень распределенное в пространстве - по всему городу (два дома тут, три дома там...), а иногда еще и по городам-спутникам.

            На компе в диспетчерской "ядро" (которое и маршрутизатор и отношение "многие-ко-многим" и монитор состояния контроллеров верхнего уровня и еще куча логики в нем), к нем по UDP подключаются контроллеры верхнего уровня (IP-шлюзы) - их там может быть штук 20.

            К каждому IP-шлюзу по RS485 подключались несколько (где-то 5-ти хватало, где-то до 30-ти доходило) контроллеров нижнего уровня (УСО - устройство сопряжения с объектом). На них уже размещались "клеммные доски", позволяющие физически подключать устройства.

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

            Механизмов мало было - дистанционные замки в служебных помещениях.

            Были устройства ГГС - громкоговорящая связь полудуплексная (со служебными помещениями, с кабинами лифтов) - там кнопка вызова + устройство коммутации линии + VoIP линия.

            Видеонаблюдение можно было подключать, еще (где просили) подключали приборы общедомового учета (чтобы данные автоматом в диспетчерскую снимались).

            В общем и целом на диспетчерской могло быть порядка тысячи устройств (одних лифтов 500-600 штук ну и остального...)

            Протокол обмена - двоичный, датаграммы где в заголовке "физический адрес устройства" (номер шлюза - номер УСО - номер клеммы) + блок данных переменной длины который интерпретировался уже в соответствии с тем что это за устройство.

            К ядру уже по TCP подключались интерфейсные клиенты. Они разных типов - диспетчер, аварийная бригада, просмотр логов и т.п.

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

            Конфигурация вся "на горячую" - сначала физически подключаем устройство к клеммам, потом на компе уже включаем его в систему (описываем - где, что, куда подключено). На соотв. УСО уходит инициализация и устройство начинает работать.

            Для новых типов были предусмотрены "драйвера" в виде DLL. Указывается в конфигурации и пришедшая датаграмма отправляется туда. А там уже вся ее обработка, вывод сообщений всех и т.п. В этом случае передо добавлением устройства добавлялся новый "тип" с указанием "драйвера".

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

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

            Все это было проще реализовать самим чем путаться вписывать в какую-то готовую скаду.

            С вебом решили не связываться. Все было в двоичном виде. Для интерфейсных клиентов в ядре был свой TCP сервер куда они подключались. Т.е. запускаешь клиент, указываешь к какому объекту подключаться (IP-адрес из справочника) и вперед - регистрация клиента в ядре и работаем.


      1. 9982th
        22.10.2023 12:44

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


        1. MiraclePtr
          22.10.2023 12:44

          Поддержку, очень интересно.

          Я бы даже сказал, было бы очень круто увидеть статью об этом.


        1. ponikrf
          22.10.2023 12:44
          +1

          Ушли с CodeSys (2?) не помню если честно. Дело в том что изначально не мы делали этот проект.

          Суть проекта - мониторинг. Тот кто это делал до нас, поставил модули ввода, завел в них датчики, поставил ПЛК, прописал это все дело в ПЛК, поставил OPC + SCADA.

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

          Вносить изменения в такую схему для меня было просто неприемлемо сложно. Взять проект ПЛК, прописать входные данные, выходные данные, залить прошивку, прописать OPC сервер и только потом получить все это дело в SCADA.

          В конечном итоге из этой схемы я выкинул все кроме модулей ввода.

          Мы экспериментировали со сборщиком на PHP но результат был не очень.

          Потом родился VRack и мы начали собирать данные им сразу в 2 базы ClickHouse и Graphite. А отображать все продолжали в Grafana.

          Отдельно хотелось бы выделить ClickHouse, боже это просто чудо. Мы делаем запросы к нашим устройствам, получаем с них данные по датчикам и сохраняем их в ClickHouse. На данный момент у нас в базе данных только по датчикам 7 533 369 159 записей, таблица занимает в базе всего 36GB. ClickHouse супер эффективная база данных для хранения именно сырых данных. Поэтому мы пихаем в нее все что считаем нужным. Например, дополнительно к получению каждой метрики по датчику мы так же сохраняем сколько времени у нас ушло на запрос. Это позволяет локализовать сетевые проблемы или проблемы с оборудованием (преобразователи или сами модули ввода).

          В ClickHouse есть агрегируемые таблицы, вам не нужно самим заниматься агрегацией, база все сделает за вас. Есть несколько движков таблиц, таблица даже может прикинутся Graphite-like таблицей.

          Если вы сами занимаетесь получением и хранением данных - рекомендую, независимо от масштаба ClickHouse.

          Такс, по поводу управления. Управление если необходимо осуществляется у нас обычно через отдельный самописный интерфейс для мобилки. С появлением Vue2/3 и VRack для меня это перестало быть хоть какой то минимальной проблемой. Вобще если вам интересно - можете глянуть могу статью про VRack.

          По поводу графаны - у нее есть для нас серьезная проблема. Графана ну слишком быстро развивается. Она работает в целом хорошо, но нас по итогу она не устроила и мы переходим сейчас на собственное решение. В итоге стек для решение тех задач у нас - VRack/VRack-db/Clickhouse/Vue3/ECharts/.

          Просто для понимания трудозатрат - все это я делаю в одного. Например новый интерфейс вместо графаны я сделал за 4 вечера и 2 выходных. Соответственно в этот интерфейс при желании я могу встроить управление, VRack мне это позволяет.

          VRack-db я использую для кеширования данных и моментального отображения графиков. Graphite хоть и хороша, но у нее есть концептуальная проблема - он очень сильно нагружает SSD, 3-4 года и SDD на выброс. Я подумал подумал и решил вобще не хранить данные на SSD для отображения графиков и просто запилить In Memory базу данных. В формате Graphite с нужной нам точностью все метрики у нас занимают в памяти не больше гигабайта. В случае чего все равно есть сырые данные в Clickhouse.

          Для меня сейчас, самое главное - это мобильность. Если инструмент не позволяет себя расширять или заменять, я на него даже не посмотрю. В OpenSource сейчас есть кучу реально крутых вещей, ClickHouse хороший тому пример.

          Получилось чет многовато. Короче как я и говорил, это тянет все на отдельную статью)


  1. AntonSor
    22.10.2023 12:44
    +1

    Спасибо, очень интересно! Надо будет где-нибудь применить. И ещё найти аналогичную систему с открытым исходным кодом, чтобы не зависеть от пропадания с гитхаба



    1. MikeKozlovAVR Автор
      22.10.2023 12:44
      +1

      Буду очень рад если пригодится!


  1. smart_pic
    22.10.2023 12:44

    Похоже вы повторили то что сделана на мониторах Nextion Но там конечно возможностей побольше будет в плане создания интерфейса и разных скриптов на события.

    Вопрос : а по ТСР эта система работает , а то только про сом порт речь идет

    Стоит лишь выбрать в каком месте на компьютере создать иконку и дать ей имя. Как только мы нажмем Accept, то по указанному пути создастся иконка приложения, при нажатии по которой, наш проект сразу запустится, и, при необходимости, откроет нужный COM-порт!


    1. MikeKozlovAVR Автор
      22.10.2023 12:44

      Кстати да, на момент создания этого софта я еще не знал про Nextion (возможно их тогда и не было, либо были не популярны), но позже когда для очередной поделки решил воспользоваться их дисплеем, то тоже подумал что есть большое сходство, особенно в плане протокола обмена. Видимо, ребята тоже старались сделать чтобы было максимально просто. Но всё же у них направление на "гуи" для дисплейного модуля, а не для работы на ПК. Для Modbus RTU и Modbus TCP предусмотрен такой элемент как "девайс", в котором можно настроить какой регистр с какого адреса привязать к тегу и прочие вещи как байт-свап и т.д. На счет автозапуска по TCP, если память не изменяет, то я такого не делал. То есть нужно будет вручную нажать "Connect all devices".


      1. NutsUnderline
        22.10.2023 12:44

        есть еще пара производителей таких HMI интерфейсов, без декларированной привязки к SCADA а чтобы красиво и редактировалось в редакторе. Но железо там не слабенькое, цена не кислая, в результате это уже не для самоделкиных...


        1. SHLab
          22.10.2023 12:44

          Боюсь далеко не пара. Что то прям очень похожее мы делали для ЖКХ в Москве еще в начале 2000-х годов ) и мы были совсем не одни на рынке )


          1. NutsUnderline
            22.10.2023 12:44

            я про тех которые можно купить не за космические для самодельщика деньги


  1. Moog_Prodigy
    22.10.2023 12:44
    +2

    Автор, вы делаете великое дело! На самом деле, многие это еще не осознают, потому что многие думают "scada это фронт, а я бэк, купят как нить". Есть маленькие проекты, типа CaScada, но все закрытое, каждый хочет свой кусок с асушного пирога урвать, а пирожок то маленький. Если для фирм\заводов платное решение да с поддержкой - нравится, то и в путь, господа.

    Есть проекты средней величины типа OpenScada. Но оно уже переусложнено, плюс разработчики из Украины....сложно.

    Можно пиратить. Но опять же как указал автор - высокий порог входа. Он не то чтобы высокий, но специфичен у каждой системы, и вот эта специфика добавляет постоянно мноооого геморроя. Система как будто говорит нам: наймите специалиста. Заплатите денег побольше! А потом еще! И еще много-много раз. Система в этом не виновата, ее такой создали разработчики, которым в свою очередь диктовали требования маркетологи. Плюс "как быть пряником и нравиться всем". Кому то не нужен OPC сервер, а какой нибудь завод скажет - о, у нас такие обьемы, конечно без серверов никуда, все будет. И выкатят им софт, которому они только и будут радоваться. Стоп. Получается только крупные заказчики и используют весь (и то не весь) функционал типичных SCADA, а на мелких плевать, и это так и есть. А те кто разрабатывают небольшие скады, хотят почему то денег. Их тоже можно понять. Но нужно понимать и сегодняшнее положение дел в асутп. Денег там 0. Спецы бегут. А кто остался - поддерживают существующее костылями. Я сам там работал, поддерживая древние скады еще под DOS, siemens S5 -115 и рулящее мощными механизмами. Это актуально до сих пор, и оно будет работать, потому что а смысл что то обновлять, если работает? Хорошо, жк экран поставим.

    Универсальность готовых продуктов - одновременно их и плюс и минус. Может подойти для любого техпроцесса. Но разворачивание и настройка превращается в кипение в котле будто ты грешник.

    Автор, твори, делай! На маленьких производствах, дома, такое очень востребовано!


    1. MikeKozlovAVR Автор
      22.10.2023 12:44

      Спасибо за теплые слова. Это решение именно для домашних проектов т.к. нет гарантий на отказоустойчивость и так далее, зато очень просто и быстро.


    1. Siemargl
      22.10.2023 12:44

      Нет, самоделки в этой области это гемор.

      /- Ой, у нас студент что то сделал, поправьте плз.

      Исходники есть?

      -Нет

      Пиратьте пока дают Сименс, ГЕ, РА

      ЗЫ. Тема очень сложная, не для самодельщиков.


      1. MikeKozlovAVR Автор
        22.10.2023 12:44

        Смотря про какой уровень идет речь, если в промышленности либо на крупных объектах то однозначно крупные системы с экосистемами, которые отлажены со временем. Если дома, для условной теплицы - то вполне что то из самоделкиных сгодится. Я, проработав несколько лет в атомной промышленности, никогда в жизни не стал бы использовать что то самодельное, даже если бы был в нем уверен так как ответственность огромная.

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