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

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

Автор Тема: Запись и чтение данных в файл + их инициализация  (Прочитано 5047 раз)

Серега

  • Старожил
  • ****
  • Сообщений: 290
    • Просмотр профиля
Добрый день!
Попросили сохранять текущее состояние процесса. Процессов может быть много. Изменение состояния процесса фиксируется флагами (через биты переменной).
Решил сделать это все через файл.
Запись при остановке проекта:
Код
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) пишутся нули. Но если стоит авто восстановление то работает все как надо.
Можете объяснить что делаю не так или опять есть нюансы работы со скриптами?
Жду вопросов и предложений.

Simple_Scada

  • Администратор
  • *****
  • Сообщений: 1414
    • Просмотр профиля
Здравствуйте.

Способ пропуска первого изменения с использованием локальной переменной(skip) работал в старых версиях скады. Начиная с версии 2.3.4.6 в компилятор были внесены изменения в работу с локальными переменными - см. "Изменение 1" по ссылке. Локальные переменные скрипта могут иметь произвольное значение в момент старта скрипта. Поэтому локальные переменные нужно обязательно инициализировать перед использованием. Поэтому такой способ не сработает в новых версиях скады и нужно создавать отдельную внутреннюю переменную в редакторе переменных и использовать в скрипте ее, а лучше для пропуска первого изменения в скрипте "Изменились переменные" использовать функцию IsFirstChange:
Код: (delphi)
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.