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

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

Автор Тема: Вопросы по скриптам в Simple-Scada 2  (Прочитано 460355 раз)

pan2000

  • Постоялец
  • ***
  • Сообщений: 213
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1635 : 29 Июля 2025, 09:55:03 »
   Здравствуйте.

... но если авария уже была и появилась новая, то значение переменной не изменилось и скрипт открытия окна не выполнится пока мы не сбросим все аварии...
Возможны два варианта:
- использовать для скрипта открытия окна изменение переменной "Счетчик ошибок";
- повторно открывать окно при попытке закрыть окно с ошибками (подобно австралийцу, который пытается выбросить старый бумеранг).

В примере два варианта:
- вызов скрипта открытия окна по счетчику ошибок;
- вызов скрипта непосредственно по битам ошибок (для случая когда все ошибки доступны в окне).
Окно закрывается после сброса всех ошибок.
Второй вариант предпочтительней для случая большого количества окон (особенно шаблонных), т.к. скрипт "Изменились переменные" будет либо включать длинные списки переменных с какой-то логикой выборки переменных для конкретного окна, либо много-много отдельных скриптов.

Цитировать
...каждом выполнении скрипта "Изменились переменные" взвожу флаг в True ...
...данный скрипт будет выполняться и выполняться,...
Если это самое "True" есть переменная вызывающая скрипт, то вероятная причина зацикливания - отсутствие в первых строках скрипта команды выхода по "False" (признак - окно без ошибок открывается при запуске проекта).

Серега

  • Старожил
  • ****
  • Сообщений: 266
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1636 : 07 Августа 2025, 17:17:47 »
Добрый день!
Скрипт универсальный, вешается на тексты с разным значением текста, но значение текста может повторяться, на событие onClick.
Нажимаем на текст с инфо и стрелка показывает где это расположено.
Писать для каждого текста через Name объекта можно, работает. Но хотел подсократить объем кода.
Понятно что вызывающий скрипт объект TM_Control. Но мы как бы приводим его к типу TM_Text, а у него уже свойство .Text есть.
Можете объяснить почему данный скрипт вызывает ошибку 'Undeclared identifier "Text", ... ':
Код: (delphi)
  with (Sender as TM_Text) do
    shWhereProblem.Visible := True;
    if Sender.Text = 'A2.2' then
    begin
      shWhereProblem.X := 506;
      shWhereProblem.Y := 744;
    end;

Хотел бы услышать мнение разработчиков.
« Изменён: 07 Августа 2025, 17:24:58 от Simple-Scada »

Simple-Scada

  • Администратор
  • *****
  • Сообщений: 3183
    • Просмотр профиля
    • Simple-Scada
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1637 : 07 Августа 2025, 17:24:47 »
Если код не заключен в begin..end, то действие будет распространяться только на первую строку.
Также не нужно писать "Sender.Text", когда выше уже использовали "with (Sender as TM_Text) do", можно сразу обращаться к свойству Text.
Исправленный код:
Код: (delphi)
with (Sender as TM_Text) do
begin
  shWhereProblem.Visible := True;
  if Text = 'A2.2' then
  begin
    shWhereProblem.X := 506;
    shWhereProblem.Y := 744;
  end;
end;

Ещё можно делать так (проще для понимания):
Код: (delphi)
var
  aText: TM_Text;
begin
  aText := Sender as TM_Text;
  shWhereProblem.Visible := True;
  if aText.Text = 'A2.2' then
  begin
    shWhereProblem.X := 506;
    shWhereProblem.Y := 744;
  end;
end.

Серега

  • Старожил
  • ****
  • Сообщений: 266
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1638 : 07 Августа 2025, 17:39:03 »
Как то упустил из виду что для with тоже надо использовать begin..end. Все заработало.
2ой способ как то нагляднее. уже завтра попробую.
Спасибо!

OlegM

  • Новичок
  • *
  • Сообщений: 12
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1639 : 10 Октября 2025, 15:16:10 »
Добрый день.

Помогите, пожалуйста, разобраться со скриптом.
Реализовал свою простенькую функцию FormatStr.
Не всегда, но достаточно часто вижу в логах сервера, вот такую ошибку на этот скрипт: 'Ошибка в скрипте Utils в строке 192. Обращение к несуществующему объекту (017C0647 . Read of address 00000028)'.
Utils -- это мой глобальный модуль, а строка 192 -- это завершающий мою функцию `end;` .

Вот сама функция:
Код: (delphi)
// === Format String ===============================================================================
// =================================================================================================
// Подставляет в строку вместо %s элементы из массива.
// Может принимать элементы для подстановки разных типов (Variant).
// Каждый элемент для подстановки рассматривается внутри функции как тип Variant,
//   который затем приводится к строке через VarToStrDef().
// Экранирование процента делается так: '%%' -> '%'.


// Стандартная делфишная функция Format() не поддерживается.


// Пример:
// FormatStr('Процент: %s%%, значение: %s.', [85, 'Ok']);
// => 'Процент: 85%, значение: Ok.'


function FormatStr(const AString: string; const Args: array of Variant): string;
var
  I, ArgIndex: Integer;
  NextSeq: string;
  V: Variant;
begin
  Result := '';
  ArgIndex := 0;
  I := 1;


  while I <= Length(AString) do
  begin
    if (AString[I] = '%') and (I < Length(AString)) then
    begin
      NextSeq := Copy(AString, I, 2); // например: '%s', '%%', '%x'


      if NextSeq = '%%' then
      begin
        Result := Result + '%';
        Inc(I, 2);
      end
      else if NextSeq = '%s' then
      begin
        if (Length(Args) > 0) and (ArgIndex <= High(Args)) then
        begin
          V := Args[ArgIndex];
          Result := Result + VarToStrDef(V, '<unsupported>');
          Inc(ArgIndex);
        end
        else
          Result := Result + '<missing>';
        Inc(I, 2);
      end
      else // неизвестная последовательность -- оставляем просто '%'
      begin
        Result := Result + '%';
        Inc(I);
      end;
    end
    else
    begin
      Result := Result + AString[I];
      Inc(I);
    end;
  end;
end;
PS: Странно, что эта функция не поддерживается из коробки. Очень удобно ей пользоваться, например, при формировании sql-запросов с несколькими подстановками.

Вот код вызова, он иногода выполняется без ошибок, а иногда с этой ошибкой по памяти.
Но! Если перед этим кодом добавить строку для записи в виртуальную переменную любого значения, то всегда работает без ошибок.
Код: (delphi)
    Test.Value := 'Ok'; // С этой строкой FormatStr всегда работает без ошибок.
    GetVariableByName(FormatStr('Ch%s_PrgName',   [ChamberNo])).Value :=           tblPrograms.GetCell(Ord( colPrgName      ), SelRow).Text;
    GetVariableByName(FormatStr('Ch%s_BoardWood', [ChamberNo])).Value :=           tblPrograms.GetCell(Ord( colPrgBoardWood ), SelRow).Text;
    GetVariableByName(FormatStr('Ch%s_BoardThk',  [ChamberNo])).Value := StrToInt( tblPrograms.GetCell(Ord( colPrgBoardThk  ), SelRow).Text );
« Изменён: 13 Октября 2025, 14:05:28 от Simple Scada »

OlegM

  • Новичок
  • *
  • Сообщений: 12
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1640 : 13 Октября 2025, 14:21:55 »
Переделал на функцию без Variant: вместо %s функция подставляет только строки из массива.
Проблема осталась. По прежнему выбивает эту ошибку 'Ошибка в скрипте Utils в строке 262. Обращение к несуществующему объекту (017C0647 . Read of address 00000028)'.
Код: (delphi)
// === FormatStr ===============================================================================
// =============================================================================================
// Функция подставляет в строку вместо '%s' строки из массива.

function FormatStr(const S: string; const Args: array of string): string;
var
  I, ArgIndex: Integer;
  NextChar: Char;
begin
  Result := '';
  ArgIndex := 0;
  I := 1;

  while I <= Length(S) do
  begin
    if (S[I] = '%') and (I < Length(S)) then
    begin
      NextChar := S[I + 1];

      if NextChar = '%' then
      begin
        Result := Result + '%';
        Inc(I, 2);
      end
      else if NextChar = 's' then
      begin
        if ArgIndex < Length(Args) then
        begin
          Result := Result + Args[ArgIndex];
          Inc(ArgIndex);
        end
        else
          Result := Result + '<missing>';
        Inc(I, 2);
      end
      else
      begin
        // неизвестная последовательность — оставляем просто '%'
        Result := Result + '%';
        Inc(I);
      end;
    end
    else
    begin
      Result := Result + S[I];
      Inc(I);
    end;
  end;
end;
« Изменён: 13 Октября 2025, 19:16:14 от Simple_Scada »

OlegM

  • Новичок
  • *
  • Сообщений: 12
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1641 : 13 Октября 2025, 14:55:58 »
Если сделать через конкатенацию, то все выполняется без ошибок.
Код: (delphi)
    // Выполняется без ошибок.
    GetVariableByName('Ch'+ IntToStr(ChamberNo) +'_PrgName'  ).Value :=           tblPrograms.GetCell(Ord( colPrgName      ), SelRow).Text;
    GetVariableByName('Ch'+ IntToStr(ChamberNo) +'_BoardWood').Value :=           tblPrograms.GetCell(Ord( colPrgBoardWood ), SelRow).Text;
    GetVariableByName('Ch'+ IntToStr(ChamberNo) +'_BoardThk' ).Value := StrToInt( tblPrograms.GetCell(Ord( colPrgBoardThk  ), SelRow).Text );
« Изменён: 13 Октября 2025, 15:03:27 от Simple Scada »

Simple-Scada

  • Администратор
  • *****
  • Сообщений: 3183
    • Просмотр профиля
    • Simple-Scada
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1642 : 13 Октября 2025, 15:26:40 »
Явно как-то портится память (скорее всего связанная со строками). Можете выслать на support@simple-scada.com проект в котором воспроизводится ошибка?
« Изменён: 13 Октября 2025, 20:40:52 от Simple-Scada »