Здравствуйте. Нужен совет.
Есть две переменных, связанных с одним устройством. Первая переменная дискретная, может принимать значения 0 или 1. Вторая переменная является счётчиком для первой типа LongWord. Есть три состояния устройства:
1-первая переменная = 0, устройство в норме;
2-первая переменная = 1, счётчик увеличился на 1, устройство в аварии;
3 - первая переменная мигает, раз в секунду изменяя своё значение (0,1,0,1,0...), вторая переменная соответственно инкрементируется на 1 каждую секунду.
Задача состоит в том, чтобы разделить эти состояния и вывести соответствующее предупреждение.
С первыми двумя состояниями вопросов не возникает. Третье состояние я решил определять с помощью скорости изменения второй переменной - счётчика. Если изменяется быстрее, какого-то значения, то считаем, что третье состояние наступило. (Возможно, Вы можете предложить лучший способ).
Написал универсальный скрипт в шаблоне для фигуры, символизирующей устройство.
var
timeOfPreviousValue: TDateTime; //хранит время
speedOfChanging: Double; //скорость изменения переменной (производная по времени)
s: String; //сообщение о неисправности
begin
if Sender is TM_Shape then
with Sender as TM_Shape do
speedOfChanging := 0.0;
timeOfPreviousValue := IncSecond(Now, -interval.value); //interval - глобальная переменная времени задержки
ArchiveValueByTime(TM_Shape(Sender).VariableEx, previousValue, timeOfPreviousValue); //запрос из архива значения, полученного на interval времени раньше
Text2.Text := IntToStr(TM_Shape(Sender).VariableEx.AsInt64); //для отладки
Text3.Text := IntToStr(previousValue.AsInt64); //для отладки
if previousValue.Value <> 0 then //проверка на тот случай, когда в архиве недостаточно данных
begin
if (TM_Shape(Sender).VariableEx.AsInt64 - previousValue.AsInt64) > 0 then //проверка на ноль
speedOfChanging := (TM_Shape(Sender).VariableEx.AsInt64 - previousValue.AsInt64)/interval.Value; //вычисление скорости изменения второй переменной
Text4.Text := FloatToStr(speedOfChanging); //для отладки
if speedOfChanging > 0.5 then //условие, при котором наступает третье состояние
begin
s := "Неисправность УКМ" + UTF8ToString(Sender.Hint);
AddMessage(Now, mkAlarm, s, true, true);
end;
end;
end.
Возникли следующие вопросы.
1. При попытке обращения к локальной переменной типа TM_Variable, в которую я передал результат функции ArchiveByTime в логе сервера появилась ошибка access violation. Поэтому создал глобальную переменную previousValue. Правильно ли я понимаю, что нет способа возвращать значение в локальную переменную? Не хотелось бы создавать отдельную переменную для каждого устройства.
2. Если создавать отдельную переменную для каждого устройства, то для работы в универсальном скрипте нужно будет использовать поиск по имени, а в имя протаскивать подстановку какого-нибудь поля? (hint, name).