Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Не получили письмо с кодом активации?

Официальный форум Simple-Scada.

Автор Тема: Реализация аналитики в Simple-Scada  (Прочитано 5350 раз)

razorqhex

  • Пользователь
  • **
  • Сообщений: 79
    • Просмотр профиля
Реализация аналитики в Simple-Scada
« : 04 Октября 2019, 12:23:46 »
Всем привет. Очень прошу помощи в реализации аналитики в Simple-Scada 2

Имеется база данных с таблицей забитой данными с тренда. Каждую секунду пишутся данные. За минуту собралось какое-то количество данных. Нужно каждые текущие данные сравнивать со вчерашними за 24 часа. Если число выше 20-ти или -20 значит нужно оповестить оператора об этом. Пересчёт числа делается по формуле:
Код
(ФактическоеЧисло / ЧислоВчера - 1) * 100
Получается каждую минуту нужно брать следующую минуту вчерашнего дня и до конца дня. Завтра уже брать данные с сегодня, послезавтра брать данные с завтра. Запутанно немного, но очень прошу помощи в реализации задания  :(
« Изменён: 07 Октября 2019, 18:26:14 от Simple-Scada »

Simple-Scada

  • Администратор
  • *****
  • Сообщений: 3214
    • Просмотр профиля
    • Simple-Scada
Re: Реализация аналитики в Simple-Scada
« Ответ #1 : 07 Октября 2019, 18:23:47 »
Здравствуйте.

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

1. Включить архивацию "по-изменению" у основной переменной, допустим её имя vrMain;
2. Создать отдельную внутреннюю переменную с тем же типом данных (в неё будем получать значение из архива). Назовём её vrArchive;
3. Создать отдельную внутреннюю переменную с типом данных Integer (будем использовать для отсчёта минут). Назовём её vrMinute;
4. Создать скрипт с типом события "прошла секунда" и получать в нём архивное значение 24 часа назад. Для этого используем такой код:
Код: (delphi)
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. Создать скрипт с типом события "Изменились переменные", добавить в него переменную vrArchive и реализовать в нём нужный пересчёт:
Код: (delphi)
var
  aCalc: Double;
begin
  { в этом скрипте нужно реализовать пересчёт.
    vrMain.Value - значение основной переменной;
    vrArchive.Value - значение основной переменной 24 часа назад; }

  // вычисляем разницу между текущим значением переменной и её значением 24 часа назад
  aCalc := vrMain.Value - vrArchive.Value;
end.

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

Также учитывайте, что функция ArchiveValueByTime является асинхронной, т.е. она создаёт запрос к БД и ждёт пока он выполнится. Не гарантируется что он всегда будет выполняться моментально. Например, если СУБД нагружена какими-то другими запросами, то ей может понадобиться какое-то время на их выполнение и результат ArchiveValueByTime будет выдан с какой-то задержкой.
« Изменён: 07 Октября 2019, 18:24:57 от Simple-Scada »

razorqhex

  • Пользователь
  • **
  • Сообщений: 79
    • Просмотр профиля
Re: Реализация аналитики в Simple-Scada
« Ответ #2 : 09 Октября 2019, 16:38:17 »
Здравствуйте  :)

Наверное Вы не правильно меня поняли. В Вашем примере данные не обновляются ежеминутно, а один раз при запуске. А разве не должно быть какие-то запросы к БД?

В прикреплённом изображении есть тренд с переменной 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
« Изменён: 09 Октября 2019, 16:42:37 от razorqhex »

Simple-Scada

  • Администратор
  • *****
  • Сообщений: 3214
    • Просмотр профиля
    • Simple-Scada
Re: Реализация аналитики в Simple-Scada
« Ответ #3 : 09 Октября 2019, 16:54:13 »
Здравствуйте.

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


Цитировать
А разве не должно быть какие-то запросы к БД?
Ещё раз прочтите наше предыдущее сообщение, там всё это описано, вот две цитаты:
Цитировать
нужно включить архивацию с типом "по-изменению" у переменной и затем брать прошлое значение из архива при помощи процедуры ArchiveValueByTime.
Цитировать
Также учитывайте, что функция ArchiveValueByTime является асинхронной, т.е. она создаёт запрос к БД и ждёт пока он выполнится.
, т.е. ArchiveValueByTime берёт значение из архива через запрос к БД. В принципе значение за прошлое время больше брать негде, только в БД.

Формулу в скрипте с типом события "Изменились переменные" можно использовать любую, по Вашему усмотрению. Не знаем что ещё можно добавить, полное решение Вашей задачи описано в нашем предыдущем сообщении.
« Изменён: 09 Октября 2019, 16:55:29 от Simple-Scada »

razorqhex

  • Пользователь
  • **
  • Сообщений: 79
    • Просмотр профиля
Re: Реализация аналитики в Simple-Scada
« Ответ #4 : 17 Октября 2019, 10:25:25 »
Simple-Scada, здравствуйте.

Да, данные считаются, спасибо большое :). У ещё один маленький вопрос:

Как я могу увидеть именно текущие данные и данные которые были 24 часа назад, именно с датой, временем и значениями чтобы увидеть за какой период именно он берёт значения за вчера и сравнивает с значениями за сегодня?

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

Simple-Scada

  • Администратор
  • *****
  • Сообщений: 3214
    • Просмотр профиля
    • Simple-Scada
Re: Реализация аналитики в Simple-Scada
« Ответ #5 : 21 Октября 2019, 09:15:34 »
Цитировать
Как я могу увидеть именно текущие данные и данные которые были 24 часа назад, именно с датой, временем и значениями чтобы увидеть за какой период именно он берёт значения за вчера и сравнивает с значениями за сегодня?
Если Вы получаете прошлое значение ArchiveValueByTime, то Вы в эту функцию должны передавать время за которое хотите получить значение. Просто выводите это время на экран. Можно вывести например в компонент Текст дату и время в виде текста. Чтобы перевести переменную типа DateTime в строку нужно использовать функцию DateTimeToStr. Все функции для работы с датой / временем описаны в этом разделе руководства.

knskey

  • Новичок
  • *
  • Сообщений: 30
    • Просмотр профиля
Re: Реализация аналитики в Simple-Scada
« Ответ #6 : 16 Апреля 2020, 11:13:10 »
Также учитывайте, что функция ArchiveValueByTime является асинхронной, т.е. она создаёт запрос к БД и ждёт пока он выполнится. Не гарантируется что он всегда будет выполняться моментально. Например, если СУБД нагружена какими-то другими запросами, то ей может понадобиться какое-то время на их выполнение и результат ArchiveValueByTime будет выдан с какой-то задержкой.
Подскажите, а как узнать, что операция выполнена. Ну т.е. что данные из БД получены. Просто если я в цикле это выполняю, то мне прежде, чем вытащить следующее значение, нужно дождаться выполнения предыдущей операции. Использую одну шлюзовую переменную  "AResVar", а время меняю.     ArchiveValueByTime(_1_Tnv, AResVar,  aDate); 

Simple-Scada

  • Администратор
  • *****
  • Сообщений: 3214
    • Просмотр профиля
    • Simple-Scada
Re: Реализация аналитики в Simple-Scada
« Ответ #7 : 17 Апреля 2020, 09:41:44 »
Сначала присвоить переменной значение вне рабочего диапазона, затем вызвать архивную процедуру и в скрипте по-изменению переменной результата отследить выполнение архивной процедуры. Допустим переменная меняется от 0 до 100, тогда сначала записываем в неё -1 и вызываем архивную процедуру:
Код: (delphi)
AResVar.Value := -1;
ArchiveValueByTime(_1_Tnv, AResVar,  aDate);

Далее создаём скрипт с типом "Изменились переменные", добавляем в него переменную AResVar и проверяем что переменная изменилась:
Код: (delphi)
if Variable.AsInt <> -1 then
begin
  // архивная процедура выполнилась, здесь выполняем какие-то действия
end;

knskey

  • Новичок
  • *
  • Сообщений: 30
    • Просмотр профиля
Re: Реализация аналитики в Simple-Scada
« Ответ #8 : 17 Апреля 2020, 10:05:57 »
ну это согласен конечно )
задача такая. по меткам времени вывести например 100 показаний аналоговых с интервалом времени 1 сек. Если я запускаю это в цикле, то нет уверенности что показание по запросу придет именно то. У меня так вообще вышло что они все одинаковые, так как цикл почти мгновенен в сравнении с временем ответа на эту процедуру я так понимаю. В итоге я реализовал схему в которой запрос делается раз в 2 сек. И тогда данные получены правильно. Но что будет если данных надо будет получить больше и что будет если нагрузка на сервер увеличится..

Simple-Scada

  • Администратор
  • *****
  • Сообщений: 3214
    • Просмотр профиля
    • Simple-Scada
Re: Реализация аналитики в Simple-Scada
« Ответ #9 : 18 Апреля 2020, 10:55:33 »
Цитировать
Если я запускаю это в цикле, то нет уверенности что показание по запросу придет именно то.
Если Вы 100 раз запускаете вычисление архивного значения в одну и ту же переменную результата с именем AResVar, то по окончанию каждого вычисления в переменную AResVar будет записан результат, а результат предыдущего вычисления будет потерян, ведь переменная только одна. Если вы хотите хранить все 100 результатов, то придётся использовать 100 разных переменных результата.

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

Цитировать
В итоге я реализовал схему в которой запрос делается раз в 2 сек.
Это совершенно ненадёжное решение. Скада не гарантирует что вычисление произойдёт за две секунды (скорость выполнения архивных процедур зависит от количества архивных процедур в очереди, от их сложности, от производительности ПК-сервера и загруженности СУБД), поэтому не удивляйтесь если в какой-то момент показания будут неправильными.

Цитировать
задача такая. по меткам времени вывести например 100 показаний аналоговых с интервалом времени 1 сек.
Если нужно получить 100 показаний из какой-то одной архивной переменной, то лучше использовать систему отчетов в которой есть готовое решение - периодический источник данных. Он позволяет очень быстро вывести архивные данные по какой-то переменной с указанным интервалом.
Если нужно извлечь архивные данные из 100 разных переменных, то система отчетов не подойдёт и придётся вызывать отдельные архивные процедуры.