Добрый день!
Попросили сохранять текущее состояние процесса. Процессов может быть много. Изменение состояния процесса фиксируется флагами (через биты переменной).
Решил сделать это все через файл.
Запись при остановке проекта:
if FileOpen('FileValue.dsl', '' ) then
begin
FileWriteInteger(sp.AsInt);
FileWriteInteger(state1.AsInt);
FileWriteInteger(state2.AsInt);
FileWriteInteger(state3.AsInt);
FileWriteInteger(stateX.AsInt);
FileClose;
end; Чтение при полном запуске:
var
skip:boolean;
begin
if skip then
begin
if FileOpen('FileValue.dsl', '') then
begin
sp.Value := FileReadInteger;
state1.Value := FileReadInteger;
state2.Value := FileReadInteger;
state3.Value := FileReadInteger;
stateX.Value := FileReadInteger;
FileClose;
end;
end
else
skip := True;
end.
Выбор конкретного процесса сделан через ComboBox (изменением значения привязанной переменной stateX, тип скрипта DataChange):
begin
case sp.value of
1 : stateX.Value := state1.Value;
2 : stateX.Value := state2.Value;
3 : stateX.Value := state3.Value;
end;
end.
Изменение конкретного флага сделано через CheckBox`ы (тип скрипта DataChange, привязка к битам переменной stateX) + запись в соответствующую переменную соответствующего процесса
begin
case sp.value of
1 : state1.Value := stateX.Value;
2 : state2.Value := stateX.Value;
3 : state3.Value := stateX.Value;
end;
Это сделан скрипт (тип изменились переменные) для записи в файл введенных изменений в течении работы проекта (текстовый файл создан что бы видеть изменения)
var
skip:Boolean;
begin
if skip then
begin
TextFileOpen('FileValue.txt', '', fomRewrite, fcpUTF8);
TextFileWriteLn(IntToStr(sp.OriginalAsInt));
TextFileWriteLn(IntToStr(state1.OriginalAsInt));
TextFileWriteLn(IntToStr(state2.OriginalAsInt));
TextFileWriteLn(IntToStr(state3.OriginalAsInt));
TextFileWriteLn(IntToStr(stateX.OriginalAsInt));
TextFileClose;
if FileOpen('FileValue.dsl', '' ) then
begin
FileWriteInteger(sp.AsInt);
FileWriteInteger(state1.AsInt);
FileWriteInteger(state2.AsInt);
FileWriteInteger(state3.AsInt);
FileWriteInteger(stateX.AsInt);
FileClose;
end;
end
else
skip := True;
end.
На форуме есть темы в которых указано как не учитывать первый скан и инициализацию переменных в ноль.
Так же есть свойство переменной "Автоматическое восстановление".
В зависимости от включена этот флаг или нет значения либо восстанавливаются как надо, либо нет.
При тестировании видно что в текстовый файл просто при включении\выключении проекта (сервер - служба Windows, версия 2.5.0.0) пишутся нули. Но если стоит авто восстановление то работает все как надо.
Можете объяснить что делаю не так или опять есть нюансы работы со скриптами?
Жду вопросов и предложений.
Здравствуйте.
Способ пропуска первого изменения с использованием локальной переменной(skip) работал в старых версиях скады. Начиная с версии 2.3.4.6 в компилятор были внесены изменения в работу с локальными переменными - см. "Изменение 1" по ссылке (https://simple-scada.com/help/script/compilerchange.html). Локальные переменные скрипта могут иметь произвольное значение в момент старта скрипта. Поэтому локальные переменные нужно обязательно инициализировать перед использованием. Поэтому такой способ не сработает в новых версиях скады и нужно создавать отдельную внутреннюю переменную в редакторе переменных и использовать в скрипте ее, а лучше для пропуска первого изменения в скрипте "Изменились переменные" использовать функцию IsFirstChange (https://simple-scada.com/help/script/isfirstchange.html):
begin
if not IsFirstChange then // пропускаем первое изменение
begin
TextFileOpen('FileValue.txt', '', fomRewrite, fcpUTF8);
TextFileWriteLn(IntToStr(sp.OriginalAsInt));
TextFileWriteLn(IntToStr(state1.OriginalAsInt));
TextFileWriteLn(IntToStr(state2.OriginalAsInt));
TextFileWriteLn(IntToStr(state3.OriginalAsInt));
TextFileWriteLn(IntToStr(stateX.OriginalAsInt));
TextFileClose;
if FileOpen('FileValue.dsl', '' ) then
begin
FileWriteInteger(sp.AsInt);
FileWriteInteger(state1.AsInt);
FileWriteInteger(state2.AsInt);
FileWriteInteger(state3.AsInt);
FileWriteInteger(stateX.AsInt);
FileClose;
end;
end;
end.