<< Click to Display Table of Contents >> Navigation: Проект > Элементы дерева объектов > Палитра ФБ > Служебные > Скрипт > Руководство и примеры > Работа с архивом данных > Обработка архивов |
Теперь рассмотрим обратную ситуацию - архив необходимо прочитать и как-либо обработать. Можно использовать для решения данной задачи штатный функционал MasterSCADA - функции работы с архивом модуля Расчет, а также тренды или редактор отчетов. Однако если требуется сложный алгоритм обработки данных - например найти максимум за какой-то интервал времени, найти значение превышающее заданное, определенное значение на интервале и т.д., то в этом случае следует использовать скрипт.
В качестве примера напишем скрипт, который будет производить поиск максимального значения за заданный интервал времени, и выдавать на выход значение и его метку времени.
Сначала подготовим необходимые для отладки компоненты. Добавим в объект команду, включим у нее архивацию и наполним ее данными - введем в нее значения вручную. Например, получится вот такой набор данных:
Теперь добавим в дерево скрипт и добавим в него Вход - на него будет поступать сигнал с нашей команды, входы времени Начало и Конец - за этот интервал мы будем искать максимум, логический вход Найти, и два выхода - Значение и МеткаВремени, в которые мы выведем результат.
Установим связь между Команда 1 и Вход.
Поиск мы будем выполнять по переднему фронту входа Найти. Также нужно убедится что Начало и Конец имеют значения, и Конец больше чем Начало.
bool? M = false;
public override void Execute()
{
if (Найти == true && M == false && Начало.HasValue && Конец.HasValue && Начало < Конец)
{
}
M = Найти;
}
Теперь можно приступить к чтению архива из входа. Можно получить переменную как мы делали при переборе переменных на прошлом шаге, но если нас интересует вход скрипта, то можно воспользоваться методом:
var elem = HostFB.InputGroup.GetPin("Вход").TreePinHlp;
Теперь мы можем обратится к архиву переменной, который находится в свойстве DataArchiveItem.
var arch=elem.DataArchiveItem;
Теперь у нас есть переменная arch, которая содержит все методы для выборки архива.
Теперь объявим локальные переменные для поиска - StartTime и EndTime.
DateTime EndTime=Конец.Value.ToUniversalTime();
DateTime StartTime=Начало.Value.ToUniversalTime();
Ранее мы уже упоминали, что архив в MasterSCADA хранится в формате UTC, поэтому и при обращении к нему нужно использовать время UTC. Поэтому мы приводим значения на входа Начало и Конец к UTC, с помощью метода ToUniversalTime().
Теперь выполним выборку из архива:
var mas=arch.Read(StartTime, EndTime, false);
У переменной arch (которая является классом архива входа), вызывается метод Read – чтение архива, в качестве аргумента ему передается время начала, конца и флаг необходимости чтения граничных данных (то есть нужно ли вернуть значения на границе заданного диапазона). Метод вернет PinValue[] – это массив класса PinValue, то есть набор состояний входа и всех его атрибутов (значение, метка времени, признак качества).
Теперь обработаем архив:
var mas = k.Read(StartTime, EndTime, false);
double? Val = null;
DateTime? TimeStamp = null;
foreach (var element in mas)
{
if (Val.HasValue == false || Convert.ToDouble(element.Value) > Val.Value)
{
Val = Convert.ToDouble(element.Value);
TimeStamp = element.Time.ToLocalTime();
}
}
Значение = Val;
МеткаВремени = TimeStamp;
Вначале объявим переменную Val – типа Double(Nullable) и переменную TimeStamp типа DateTime(Nullable), эти переменные и получат значение и метку времени найденного максимума.
Затем перебираем переменные в цикле foreach, который каждое значение поочередно кладет в переменную element, которая имеет тип PinValue. После мы проверяем, если значение Val пустое и равно null, то мы сохраняем его значение и метку времени. Аналогично мы делаем если значение есть, но новое значение больше сохраненного. Затем выводим результат.
Итоговый код будет выглядеть следующим образом.
public partial class ФБ : ScriptBase
{
bool? M = false;
public override void Execute()
{
if (Найти == true && M == false && Начало.HasValue && Конец.HasValue && Начало < Конец)
{
var elem = HostFB.InputGroup.GetPin("Вход").TreePinHlp;
var k = elem.DataArchiveItem;
DateTime EndTime = Конец.Value.ToUniversalTime();
DateTime StartTime = Начало.Value.ToUniversalTime();
var mas = k.Read(StartTime, EndTime, false);
double? Val = null;
DateTime? TimeStamp = null;
foreach (var element in mas)
{
if (Val.HasValue == false || Convert.ToDouble(element.Value) > Val.Value)
{
Val = Convert.ToDouble(element.Value);
TimeStamp = element.Time.ToLocalTime();
}
}
Значение = Val;
МеткаВремени = TimeStamp;
}
M = Найти;
}
}
Данный код легко адаптировать под любую другую задачу - исправить код в цикле foreach, согласно вашей задаче.
Проверим работу скрипта. Запустим режим исполнения, зададим Начало и Конец и запустим поиск.
Будет выведено максимальное значение и метка его времени.
Готовый скрипт можно скачать по ссылке.
Однако у данного скрипта есть одна проблема - его можно использовать только в проектах с файловым архивом, и на небольших выборках. Если же используется БД (особенно удаленная), или нужно делать большие и частые выборки в автоматическом режиме, то необходимо сделать асинхронный запрос - подробнее в следующем шаге.