Допустим в проекте имеются переменные, которые хранят нарастающее значение объема воды, показаний электроэнергии, веса или какой-либо другой нарастающей величины. Иногда на основе таких переменных требуется произвести расчет объема за сутки, час, минуту и т.д. Рассмотрим решение данной задачи на примере расчета объема воды за сутки.
Важно! Следует учитывать, что во время перезапусков сервера Simple-Scada(или когда проект остановлен) архивация не ведется, следовательно архивных данных за этот момент времени не будет. Поэтому, все расчеты приведенные ниже будут корректны только если проект будет работать стабильно и без перерывов. Если не нужна зависимость от работы скада-системы и ПК, то нужно производить подобные расчеты в программе контроллера.
Расчет объема за сутки:
Для решения задачи необходимо:
1.Включить архивацию "по-изменению" у переменной, на основе которой необходимо производить расчеты. В нашем случае это будет переменная расхода с именем "vrFlow";
2.Создать две отдельные внутренние переменные с тем же типом данных, что и у переменной "vrFlow". В них будут записываться архивные значения переменной vrFlow на начало и конец интервала расчета. Назовем их vrNowFlow и vrOldFlow;
3.Для извлечения значений из архива можно использовать процедуру ArchiveValueByTime;
4.Создать скрипт с типом события "Начало часа" и получить в нем архивные значения на начало и конец интервала расчета. Для этого используем такой код:
var
aDate: TDateTime;
begin
// если сейчас 00 часов, то запускаем вычисление расхода за последние сутки
if HourOf(Now) = 0 then
begin
aDate := RecodeTime(Now, 0, 0, 0, 0); // текущее время/дата
// добавляем все последующие вызовы архивных процедур в группу с тегом = 1
ArchiveGroupBegin(1);
// извлечь из архива значение переменной "vrFlow" в отметке
// времени "aDate" и записать результат в переменную "vrNowFlow"
ArchiveValueByTime(vrFlow, vrNowFlow, aDate);
// извлечь из архива значение переменной "vrFlow" в отметке
// времени "aDate" и записать результат в переменную "vrOldFlow"
aDate := IncDay(aDate, -1); // время/дата день назад
ArchiveValueByTime(vrFlow, vrOldFlow, aDate);
// заканчиваем группировку архивных процедур
ArchiveGroupEnd;
end;
end.
Архивные процедуры не выполняются мгновенно - подробнее см. по ссылке. Поэтому нельзя работать с переменными результата(в нашем случае vrNowFlow и vrOldFlow) в том же скрипте, где вызываются архивные процедуры. Вместо этого необходимо использовать группировку архивных процедур через ArchiveGroupBegin/ArchiveGroupEnd и работать с результатами вычислений в скрипте с типом события "Выполнены архивные процедуры". В скрипте выше, все вызовы архивных процедур между ArchiveGroupBegin и ArchiveGroupEnd будут объединены в группу с заданым тегом (в данном случае = 1).
Созданный нами скрипт будет выполняться раз в сутки, в 00:00. После выполнения данного скрипта в переменную vrNowFlow будет записано значение расхода на время 00:00, а в переменную vrOldFlow значение расхода день назад, на тоже время. Для получения расхода за сутки необходимо вычесть значение vrOldFlow из vrNowFlow. Для этого нужно создать новый скрипт с типом события "Выполнены архивные процедуры" и написать код расчета:
begin
// если группа архивных процедур с тегом = 1 выполнилась
if ArcGroupTag = 1 then
// рассчитываем объем воды за сутки
vrVolume.Value := vrNowFlow.Value - vrOldFlow.Value;
end.
Задача решена, теперь каждые сутки в 00:00 будет производиться расчет объема воды и результат будет записываться в переменную vrVolume. Чтобы вычисленное значение объема сохранялось при перезапусках проекта, можно у переменной vrVolume включить опцию "Автоматическое восстановление".
Расчет объема за час:
Аналогично примеру выше, нужно создать скрипт с типом события "Начало часа" и извлекать в нем архивные значения на начало и конец часа, с применением группировки архивных процедур. Пример кода:
var
aDate: TDateTime;
begin
// добавляем все последующие вызовы архивных процедур в группу с тегом = 2
ArchiveGroupBegin(2);
aDate := RecodeTime(Now, HourOf(Now), 0, 0, 0); // текущее время/дата
// извлечь из архива значение переменной "vrFlow" в отметке
// времени "aDate" и записать результат в переменную "vrNowHourFlow"
ArchiveValueByTime(vrFlow, vrNowHourFlow, aDate);
// извлечь из архива значение переменной "vrFlow" в отметке
// времени "aDate" и записать результат в переменную "vrOldHourFlow"
aDate := IncHour(aDate, -1); // время/дата час назад
ArchiveValueByTime(vrFlow, vrOldHourFlow, aDate);
// заканчиваем группировку архивных процедур
ArchiveGroupEnd;
end.
Данный скрипт будет выполняться в начале каждого часа. Расчет объема по переменным vrNowHourFlow и vrOldHourFlow производится аналогично примеру выше - нужно создать новый скрипт с типом события "Выполнены архивные процедуры" и написать код расчета, например:
begin
// если группа архивных процедур с тегом = 2 выполнилась
if ArcGroupTag = 2 then
// рассчитываем объем воды за час
vrHourVolume.Value := vrNowHourFlow.Value - vrOldHourFlow.Value;
end.
Расчет объема за минуту:
Для расчета объема за минуту, нужно создать скрипт с типом события "Таймер" (в параметре скрипта "Интервал" указать значение 60 сек.) и извлекать в нем архивные значения на начало и конец минуты, с применением группировки архивных процедур. Пример кода:
var
aDate: TDateTime;
begin
// добавляем все последующие вызовы архивных процедур в группу с тегом = 2
ArchiveGroupBegin(3);
aDate := Now; // текущее время/дата
// извлечь из архива значение переменной "vrFlow" в отметке
// времени "aDate" и записать результат в переменную "vrNowMinuteFlow"
ArchiveValueByTime(vrFlow, vrNowMinuteFlow, aDate);
aDate:= IncMinute(Now, -1); // текущее время/дата минуту назад
// извлечь из архива значение переменной "vrFlow" в отметке
// времени "aDate" и записать результат в переменную "vrOldMinuteFlow"
ArchiveValueByTime(vrFlow, vrOldMinuteFlow, aDate);
// заканчиваем группировку архивных процедур
ArchiveGroupEnd;
end.
Данный скрипт будет выполняться раз в минуту. Для редактирования параметра "Интервал" в уже созданном скрипте, необходимо выбрать нужный скрипт с типом "Таймер" на панели скриптов и нажать кнопку редактирования(с иконкой карандаша).
Расчет объема по переменным vrNowMinuteFlow и vrOldMinuteFlow производится аналогично примерам выше - нужно создать новый скрипт с типом события "Выполнены архивные процедуры" и написать код расчета, например:
begin
// если группа архивных процедур с тегом = 3 выполнилась
if ArcGroupTag = 3 then
// рассчитываем объем воды за минуту
vrMinuteVolume.Value := vrNowMinuteFlow.Value - vrOldMinuteFlow.Value;
end.