6.3 Сессии исполнения проектов -- Выполнено
Целями данного этапа является:
- Реализация сеансов исполнения проектов на уровне модели данных СВУ в модуле UI.VCAEngine:
- Формирование иерархического дерева виджетов конечной визуализации на основе проекта, для которого открывается сеанс.
- Формирование кадров значений для процедур обсчёта виджетов конечной визуализации.
- Обработка ссылок на параметры источников данных OpenSCADA.
- Реализация иерархического обсчёта процедур и обновления ссылок виджетов.
- Формирование механизма прохождения и обработки событий по иерархическому дереву.
- Реализация визуализации сеансов проектов в модуле представления UI.Vision(QT) как полноценного пользовательского интерфейса с элементами визуализации динамики, истории и управления:
- Формирование окна исполнения проекта (RunTime).
- Визуализация кадров проекта в режиме "RunTime" с периодическим обновлением содержимого.
- Реализация передачи и обработки событий.
- Реализация механизма переключения/открытия/замещения/навигации по страницам проекта с учётом сценариев обработки.
На данном этапе был добавлен механизм исполнения проекта в сеансах модели данных модуля VCAEngine, а также визуализация сеанса проекта, режим "RunTime" в модуле визуализации на библиотеке QT Vision с элементами обновления данных и интерактивного взаимодействия с пользователем.
Формирование иерархического дерева виджетов конечной визуализации на основе проекта для которого открывается сеанс.
В соответствии с рис.4.10.1 и рис.4.10.2 объекты сессии проекта наследуются от абстрактного объекта Widget и используют соответствующие объекты проекта. Так, сессия (Session) использует проект (Project) и формирует развёрнутое дерево на основе него. Страница проекта Page прямо используется страницей сессии SessPage. Остальные объекты (SessWdg) разворачиваются в соответствии с иерархией элементов страницы (рис.4.10.2).
В дополнение к стандартным свойствам абстрактного виджета (Widget) элементы страницы и сами страницы, сессии получают свойства хранения кадра значений вычислительной процедуры, обсчёта процедур и механизм обработки событий. Страницы сессии, в дополнение ко всему, содержат контейнер следующих по иерархии страниц. Сессия в целом обсчитывается с указанной периодичностью и в последовательности:
- "Страница верхнего уровня" -> "Страница нижнего уровня"
- "Виджет нижнего уровня" -> "Виджет верхнего уровня"
Такая политика позволяет обходить страницы в соответствии с иерархией, а событиям в виджетах всплывать наверх за одну итерацию.
В сессии реализована поддержка специальных свойств страниц:
Container - страница является контейнером для нижележащих страниц;
Template - страница является шаблоном для нижележащих страниц;
Empty - пустая неактивная страница, это свойство используется совместно со свойством Container для организации логических контейнеров.
На основе этих свойств реализованы следующие типы страниц:
Standard -- Стандартная страница (не установлено ни одно из свойств). Является полноценной конечной страницей.
Container -- Полноценная страница со свойством контейнера (Container).
Logical container -- Логический контейнер, фактически неявляющийся страницей (Container|Empty). Выполняет свойство промежуточного и группирующего элемента в дереве страниц.
Template -- Страница шаблон (Template). Чистая шаблонная страница используется для описания общих свойств и доопределения их в частном порядке во вложенных страницах.
Container and template -- Страница шаблон и контейнер (Template|Container). Совмещает функции шаблона и контейнера.
Формирование кадров значений для процедур обсчёта виджетов конечной визуализации.
В разделе выше мы уже отмечали, что виджет сессии содержит кадр значений процедуры обсчёта. Этот кадр инициируется и используется в случае наличия процедуры обсчёта. В момент инициализации создаётся перечень параметров процедуры и выполняется компиляция процедуры с этими параметрами в модуле, реализующем выбранный язык программирования, и закодированным полным именем виджета. Скомпилированная функция подключается к кадру значений процедуры обсчёта. Далее выполняется вычисление с периодичностью сессии.
Вычисление и обработка виджета в целом выполняется в следующей последовательности:
- выбирается события, доступные на момент вычисления, из атрибута "event" виджета;
- события загружаются в параметр "event" кадра вычисления;
- загружаются значения по входным связям в кадр вычисления;
- загружаются значения специальных переменных в кадр вычисления (f_frq, f_start и f_stop);
- загружаются значения выбранных параметров виджета в кадр вычисления;
- вычисление;
- выгрузка значений кадра вычисления в выбранные параметры виджета;
- выгрузка значений кадра вычисления по выходным связям;
- выгрузка события из параметра "event" кадра вычисления;
- обработка событий и передача не обработанных на уровень выше.
Обработка ссылок на параметры источников данных OpenSCADA.
При исполнении виджета сеанса необходимо выполнение обработки ссылок. На данный момент подключение по ссылкам выполняется в момент вычисления, что является небыстрой операцией. Реализация обработки ссылок будет пересмотрена и оптимизирована в дальнейшем.
Заложена поддержка следующих типов ссылок:
- Значение константы ("V"). Переменная для определения в момент конфигурации страницы в проекте.
- Атрибут параметра подсистемы "Сбор данных" ("P"). Механизм доступа к значениям параметра подсистемы "Сбор данных" системы OpenSCADA.
- Атрибут вложенного виджета ("W"). Внутренняя прямая связь между вложенными виджетами.
На данный момент реализованы первые два типа ссылок. Последняя будет реализована вместе с реализацией базового виджета "Link".
Формирование окна исполнения проекта (RunTime).
На стороне визуализации (модуль Vision) для визуализации процесса исполнения проекта реализован объект VisRun. При запуске он шлёт запрос на создание и инициализацию сессии. Далее выполняется запрос на перечень открытых страниц. Исходя из информации об открытых страницах VisRun и их связности, формируется результирующий интерфейс. На рис. 6.3 приведён пример классического SCADA интерфейса с объектами сигнализации, где главное окно содержит страницу внутри, которая замещается по нажатию на кнопки объектов сигнализации и листания.
Рис.6.3 Окно визуализации исполнения проекта. Режим "RunTime".
Визуализация кадров проекта в режиме "RunTime" с периодическим обновлением содержимого.
Реализовано обновление содержимого открытых страниц интерфейса визуализации с периодичностью исполнения сессии проекта. В процессе обновления выполняется:
- запрос списка открытых страниц у модели и проверка соответствия реально открытых страниц этому списку;
- запрос изменённых данных по каждой странице и её виджету;
- обновление содержимого страниц и их виджетов в соответствии с полученными измененными данными.
По закрытию "RunTime" окна производится и закрытие сессии проекта в модели данных. В дальнейшем будет реализована возможность подключения к ранее открытой сессии и отключение от сессии, без её закрытия.
Механизм запроса только изменённых данных основан на абсолютном счётчике исполнения сессии. При внесении реальных изменений в атрибуты виджетов выполняется запоминание значения этого счётчика, что и позволяет идентифицировать изменённые атрибуты. Такой подход позволяет повысить производительность и уменьшить нагрузку на трафик в случае доступа к модели через сеть.
Реализация передачи и обработки событий.
Визуализатор сессии ("RunTime"), в виду своего непосредственного контакта с пользователем, собирает различные события. Часть событий обрабатывается образами базовых виджетов (Text, Box, Document и т.д.), в результате чего могут формироваться другие события. Другая часть прямо передаётся в модель данных, где они и обрабатываются.
В модель данных события передаются сразу после получения, где они собираются в атрибуте виджета "event" до момента следующей итерации исполнения сессии. Далее, в процессе обсчёта сессии, события извлекаются из атрибута "event" и обрабатываются в процедуре виджета или в соответствии со сценарием в атрибуте "evProc". Не обработанные событие поднимаются к вышестоящему виджету модели.
Реализация механизма переключения/открытия/замещения/навигации по страницам проекта с учётом сценариев обработки.
Переключение, открытие, замещение и навигация по страницам реализовано на основе обработки событий по сценарию, в атрибуте активного виджета "evProc". Сценирий этого атрибута записывается в виде списка команд с синтаксисом: <event>:<srcWdg>:<com>:<prm>
где:
event -- ожидаемое событие;
srcWdg -- дочерний виджет - источник события
com -- команда сессии;
prm -- параметр команды;
Реализованы следующие команды:
open -- Открытие страницы. Открываемая страница указывается в параметре prm как на прямую, так и в виде шаблона (например: /pg_so/1/*/*).
next -- Открытие следующей страницы. Открываемая страница указывается в параметре prm как на прямую, так и в виде шаблона (например: /pg_so/*/*/$).
prev -- Открытие предыдущей страницы. Открываемая страница указывается в параметре prm как на прямую, так и в виде шаблона (например: /pg_so/*/*/$).
Специальные символы шаблона расшифровываются следующим образом:
pg_so -- Прямое имя требуемой страницы, с префиксом. Требует обязательного соответствия и используется для идентификации предыдущей открытой страницы.
1 -- Имя новой страницы в общем пути, без префикса. Имя предыдущей страницы игнорируется.
* -- Страница берётся с имени предыдущей открытой страницы или подставляется первая доступная страница, если предыдущая открытая страница отсутствует.
$ -- Указывает на место открытой страницы относительно которой необходимо искать следующую или предыдущую.
Для понимания работы механизма шаблонов приведём несколько реальных примеров:
Переключение объекта сигнализации:Команда: open:/pg_so/2/*/*
Было: /pg_so/pg_1/pg_mn/pg_1
Стало: /pg_so/pg_2/pg_mn/pg_1
Переключение вида:
Команда: open:/pg_so/*/gkadr/*
Было: /pg_so/pg_1/pg_mn/pg_1
Стало: /pg_so/pg_1/pg_gkadr/pg_1
Следующая/предыдущая страница вида:
Команда: next:/pg_so/*/*/$
Было: /pg_so/pg_1/pg_mn/pg_1
Стало: /pg_so/pg_1/pg_mn/pg_2
В связке с выше описанным механизмом, на стороне визуализации (RunTime), построена логика, регулирующая каким образом открывать страницы. Логика построена на следующих атрибутах базового элемента "Box":
pgOpen -- Признак "Страница открыта".
pgNoOpenProc -- Признак "Исполнять страницу даже если она не открыта".
pgOpenSrc -- Содержит адрес виджета или страницы, открывшей текущую. В случае вложенного контейнерного виджета здесь содержится адрес включаемой страницы.
pgGrp -- Группа страниц. Используется для связки контейнеров страниц со страницами в одной группе.
Логика определения способа открытия страниц работает следующим образом:
- если страница имеет группу "main" или совпадает с группой страницы в главном окне или нет страницы на главном окне, то открывать страницу в главном окне;
- если страница имеет группу, которая совпадает с группой одного из контейнеров текущей страницы, то открыть в этом контейнере;
- если источник открытия страницы совпадает с текущей страницей, то открыть в виде дополнительного окна над текущей страницей;
- передать вызов на запрос открытия дополнительным окнам с обработкой у каждого по первым трем пунктам;
- если ни кто из родственных окон не открыл новую страницу то открыть её как родственное окно главного окна.
Совокупность всех этих механизмов уже сейчас позволяет строить сложные, многоуровневые и многооконные интерфейсы пользователя.