Всем привет. Очень прошу помощи в реализации аналитики в Simple-Scada 2
Имеется база данных с таблицей забитой данными с тренда. Каждую секунду пишутся данные. За минуту собралось какое-то количество данных. Нужно каждые текущие данные сравнивать со вчерашними за 24 часа. Если число выше 20-ти или -20 значит нужно оповестить оператора об этом. Пересчёт числа делается по формуле:
(ФактическоеЧисло / ЧислоВчера - 1) * 100
Получается каждую минуту нужно брать следующую минуту вчерашнего дня и до конца дня. Завтра уже брать данные с сегодня, послезавтра брать данные с завтра. Запутанно немного, но очень прошу помощи в реализации задания :(
Здравствуйте.
Чтобы получить данные переменной за прошлое время, нужно включить архивацию с типом "по-изменению" у переменной и затем брать прошлое значение из архива при помощи процедуры ArchiveValueByTime (https://simple-scada.com/help/script/archivevaluebytime.html). Также в Вашем случае нужно использовать скрипт-таймер для пересчёта каждую минуту. Далее решение задачи по шагам:
1. Включить архивацию "по-изменению" у основной переменной, допустим её имя vrMain;
2. Создать отдельную внутреннюю переменную с тем же типом данных (в неё будем получать значение из архива). Назовём её vrArchive;
3. Создать отдельную внутреннюю переменную с типом данных Integer (будем использовать для отсчёта минут). Назовём её vrMinute;
4. Создать скрипт с типом события "прошла секунда" и получать в нём архивное значение 24 часа назад. Для этого используем такой код:
var
aDate: TDateTime;
begin
vrMinute.Value := vrMinute.Value + 1; // накапливаем секунды в vrMinute
if vrMinute.Value >= 60 then // если накоплено 60 сек.
begin
aDate := IncHour(Now, -24); // текущие дата и время минус 24 часа
{ извлечь из архива значение переменной "vrMain" в отметке времени "aDate" и записать результат в переменную "vrArchive" }
ArchiveValueByTime(vrMain, vrArchive, aDate);
vrMinute.Value := 0; // сбрасываем счётчик секунд
end;
end.
5. Создать скрипт с типом события "Изменились переменные" (https://simple-scada.com/help/script/changemulvar.html), добавить в него переменную vrArchive и реализовать в нём нужный пересчёт:
var
aCalc: Double;
begin
{ в этом скрипте нужно реализовать пересчёт.
vrMain.Value - значение основной переменной;
vrArchive.Value - значение основной переменной 24 часа назад; }
// вычисляем разницу между текущим значением переменной и её значением 24 часа назад
aCalc := vrMain.Value - vrArchive.Value;
end.
Учитывайте, что во время перезапусков сервера (или когда проект приостановлен) архивация не ведётся и следовательно архивных данных за этот момент времени не будет, а значит вся эта система будет работать только если проект будет работать стабильно без перерывов более 24 часов. Если не нужна зависимость от скады, то нужно делать такую систему в программе контроллера.
Также учитывайте, что функция ArchiveValueByTime является асинхронной, т.е. она создаёт запрос к БД и ждёт пока он выполнится. Не гарантируется что он всегда будет выполняться моментально. Например, если СУБД нагружена какими-то другими запросами, то ей может понадобиться какое-то время на их выполнение и результат ArchiveValueByTime будет выдан с какой-то задержкой.
Здравствуйте :)
Наверное Вы не правильно меня поняли. В Вашем примере данные не обновляются ежеминутно, а один раз при запуске. А разве не должно быть какие-то запросы к БД?
В прикреплённом изображении есть тренд с переменной vrAnalyticsInTrend типа Integer. Допустимые значения -20...20. При привешенных значениях нужно оповещать оператор об этом. Но это не проблема.
Существует такая БД chaplynkadatabase, в ней же есть таблица trends_data и там есть поля Timestamp и value
Так вот, нужно текущие данные с текущим числом сравнивать со вчерашними данными. Каждую секунду эти данные записываются и за минуту они накопились. И получается ежеминутно нужно сравнивать все данные вчерашнего дня с теущим.
Чтобы понять есть ли проблема (пробита труба или же нехватка воды в РЧВ (резервуар чистой воды) или слишком много воды) есть формула:
(NФактическое число / NВчерашнее число - 1) * 100;
Текущие данные:
Timestamp Value
2019-10-09 15:31:10 39
Вчерашние данные:
Timestamp Value
2019-10-08 15:31:10 10
Сначала присвоить переменной значение вне рабочего диапазона, затем вызвать архивную процедуру и в скрипте по-изменению переменной результата отследить выполнение архивной процедуры. Допустим переменная меняется от 0 до 100, тогда сначала записываем в неё -1 и вызываем архивную процедуру:
AResVar.Value := -1;
ArchiveValueByTime(_1_Tnv, AResVar, aDate);
Далее создаём скрипт с типом "Изменились переменные" (https://simple-scada.com/help/script/changemulvar.html), добавляем в него переменную AResVar и проверяем что переменная изменилась:
if Variable.AsInt <> -1 then
begin
// архивная процедура выполнилась, здесь выполняем какие-то действия
end;