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

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

Автор Тема: Таблицы и TM_DataSet ч.2  (Прочитано 1161 раз)

Серега

  • Постоялец
  • ***
  • Сообщений: 209
    • Просмотр профиля
Таблицы и TM_DataSet ч.2
« : 20 Октября 2020, 13:48:53 »
Добрый день!
В ходе экспериментов наткнулся на ситуацию.
1. Формируем запрос в БД и вешаем на кнопку универсальный скрипт.
2. Таблица заполняется данными.
3. Создан скрипт по изменению значения переменных (2 генератора, один на ОРС сервере, второй секундный скрипт), где повторяется шаг 21 для разных таблиц:
Код
case TU4430M01_001_State_v.Value of
0 :
  begin
    if TU4430M01_001_StartLoad_v.Value = 1 then
    begin
      TU4430M01_001_State_v.Value := 1;
      TU4430M01_001_StartLoad_v.Value := 0;
      TU4430M01_0011RCS000_wProfileCmd_Set.Value := $0FFF;
    end;
  end;

 //*************************************  ЗАГРУЗКА ГЕОМЕТРИИ  **********************************************
1 :
  begin
    if (TU4430M01_0011RCS000_wProfileCmd_Set.Value = $0FFF) AND (TU4430M01_0011RCS000_wProfileCmd_Get.Value = $0FFF) then
    begin
      TU4430M01_001_State_v.Value := 21;
      TU4430M01_0011RCS000_wProfileCmd_Set.Value := 0;
    end;
  end;

21 :
  begin
    // --- проверка на совпадение количества строк в выбранной таблице, если выбрана другая таблица обнуление счетчика ---
    if tblGeometryWays.RowCount <> RowCountGeoOld then
    begin
      TU4430M01_001_State_v.Value := 0;
      TU4430M01_0011RCS000_wProfileCmd_Set.Value := $FFFF;
      Exit;
    end;
    //  ---
    if TU4430M01_0011RCS000_wProfileCmd_Get.Value = (tblGeometryWays.RowCount - 1) then
    begin
      TU4430M01_0011RCS000_wProfileCmd_Set.Value := $1FFF;
      TU4430M01_001_State_v.Value := 22;
    end
    else
    begin
      // присвоение значений из таблицы переменным Set
      if TU4430M01_0011RCS000_wProfileCmd_Get.Value = TU4430M01_0011RCS000_wProfileCmd_Set.Value then
      begin
1строка ->  TU4430M01_0011RCS001_iProfile_Set.Value := 10*StrToFloat(UTF8ToString(tblGeometryWays.Columns(1).Cells(TU4430M01_0011RCS000_wProfileCmd_Set.Value+1).Text));  // скорость
        TU4430M01_0011RCS002_iProfile_Set.Value := 10*StrToFloat(UTF8ToString(tblGeometryWays.Columns(2).Cells(TU4430M01_0011RCS000_wProfileCmd_Set.Value+1).Text));  // ускорение
        TU4430M01_0011RCS003_iProfile_Set.Value := 10*StrToFloat(UTF8ToString(tblGeometryWays.Columns(4).Cells(TU4430M01_0011RCS000_wProfileCmd_Set.Value+1).Text));  //замедление
        TU4430M01_0011RCS004_iProfile_Set.Value := 10*StrToFloat(UTF8ToString(tblGeometryWays.Columns(5).Cells(TU4430M01_0011RCS000_wProfileCmd_Set.Value+1).Text));  //рывок
        if (TU4430M01_0011RCS001_iProfile_Get.Value = TU4430M01_0011RCS001_iProfile_Set.Value)
        and (TU4430M01_0011RCS002_iProfile_Get.Value = TU4430M01_0011RCS002_iProfile_Set.Value)
        and (TU4430M01_0011RCS003_iProfile_Get.Value = TU4430M01_0011RCS003_iProfile_Set.Value)
        and (TU4430M01_0011RCS004_iProfile_Get.Value = TU4430M01_0011RCS004_iProfile_Set.Value) then
        begin
          TU4430M01_0011RCS000_wProfileCmd_Set.Value:= TU4430M01_0011RCS000_wProfileCmd_Set.Value + 1;
        end;
      end;
    end;
  end;
...
Первая строка вызывает достаточно часто на сервере ошибку следующего содержания:
Код
"Ошибка в скрипте "LoadData" в строке 101. Access violation at address 0113A04A in module 'Server.exe'. Read of address 00000034"
.
Если перед ней и после нее поставить
Код
AddMessage(Now, mkMessage, 'до' + TU4430M01_0011RCS001_iProfile_Set.Value, True, False);
и
Код
AddMessage(Now, mkMessage, 'после' + TU4430M01_0011RCS001_iProfile_Set.Value, True, False);
то если на сервере подряд мы наблюдаем выше описанную ошибку 3 раза, то на клиенте мы видим сообщения
до 200
до 200
до 200
до 200
после 300
...
Создается такое впечатление, что мы не можем какое то время получить данные, что и вызывает эту ошибку.
Возможно то, что у нас 2 генератора меняются. Но скрипт по  изменению для этого и предназначен.
В общем может дадите направление?
       

Simple-Scada

  • Администратор
  • *****
  • Сообщений: 2998
    • Просмотр профиля
    • Simple-Scada
Re: Таблицы и TM_DataSet ч.2
« Ответ #1 : 20 Октября 2020, 15:36:02 »
Здравствуйте.

Не совсем понятно что именно от нас требуется. Это обычная ошибка которая зависит только от правильности кода скрипта. Если при выполнении какого-либо скрипта в скаде возникает ошибка "Access violation", то выполнение скрипта прерывается и скрипт не выполняется дальше. Сообщение об ошибке выводится в журнал сервера, в журнале указывается номер строки в котором возникла ошибка. Ошибка говорит о том, что в скрипте выполняется обращение по неправильному указателю. Вот простейший пример:
Код
var
  aObject: TM_Object;
begin
  aObject := nil;  // записываем нулевой указатель в переменную aObject
  aObject.Visible := false;  // пытаемся изменить свойство и получаем Access Violation, т.к. aObject ссылается на nil, а не на реальный объект
end;

Чтобы таких ошибок не возникало нужно правильно писать код скриптов и где необходимо добавлять проверки на существование объекта. Примеров такой ошибки может быть очень много. Можно создать таблицу с 10 строками, а в коде обратиться к 11 строке. Или таблицу с 2 колонками, а в коде обратиться к несуществующей 3 колонке. Можно выполнить поиск переменной по несуществующему имени и попытаться обратиться к ненайденной переменной. И т.д., во всех случаях будет Access Violation, т.к. программист написал скрипт с ошибками. Мы не можем как-то запретить это, т.к. на этапе разработки и написания скрипов компилятор ничего не знает о том, какие значения будут у указателей и объектов.

Судя по тексту ошибки у Вас в скрипте LoadData идёт обращение к неправильному указателю в строке 101. Мы не знаем что происходит в строке 101, поэтому дополнительно не можем её прокомментировать.

Вы в воде выделили строку:
Цитировать
1строка ->  TU4430M01_0011RCS001_iProfile_Set.Value := 10*StrToFloat(UTF8ToString(tblGeometryWays.Columns(1).Cells(TU4430M01_0011RCS000_wProfileCmd_Set.Value+1).Text));  // скорость
Может это и есть 101 строка? Если это она и в ней возникает Access Violation, значит в момент выполнения скрипта не существует колонка с индексом 1, либо не существует ячейка с индексом "TU4430M01_0011RCS000_wProfileCmd_Set.Value + 1". В теории переменная TU4430M01_0011RCS000_wProfileCmd_Set может быть равна чему угодно, мы о ней ничего не знаем. и если она равна 100, а колонок в таблице всего 50, то будет попытка обратиться к несуществующей 101 ячейке в строке и возникнет Access Violation.

pavel.sheva

  • Новичок
  • *
  • Сообщений: 15
    • Просмотр профиля
Re: Таблицы и TM_DataSet ч.2
« Ответ #2 : 16 Августа 2022, 14:51:24 »
На данный момент есть возможность, построить таблицу, автоматически, под таблицу из БД, с авто настройкой ширины(ну или ее небольшой настройкой в коде)столбцов ?
« Изменён: 18 Августа 2022, 11:30:46 от Simple-Scada »

Simple_Scada

  • Администратор
  • *****
  • Сообщений: 1173
    • Просмотр профиля
Re: Таблицы и TM_DataSet ч.2
« Ответ #3 : 17 Августа 2022, 13:28:17 »
Здравствуйте.

У компонента "Таблица" есть свой внутренний метод RunSQL, который удобно использовать для того, чтобы отобразить результат выполнения SQL-запроса в таблице на мнемосхеме. Скада выполнит SQL-запрос, а после выполнения автоматически отобразит результат в таблице. При этом, количество строк таблицы будет соответствовать количеству строк таблицы из БД. При этом, изменить количество столбцов, размеры таблицы, высоту/ширину строк или столбцов и другие свойства таблицы автоматически или через скрипты невозможно.

pavel.sheva

  • Новичок
  • *
  • Сообщений: 15
    • Просмотр профиля
Re: Таблицы и TM_DataSet ч.2
« Ответ #4 : 17 Августа 2022, 13:41:18 »
Да, только при этом нужно за ранее в этой таблице указать кол-во колонок, иначе выведется половина таблицы, а то и меньше столбцов... такая себе работa с таблицей...