Вопросы по скриптам в Simple-Scada 2

Автор Simple-Scada, 29 января 2016, 15:19:20

596039

Для перехода в группу трендов из универсального окна.

Simple-Scada

#181
Здесь возникнет одна проблема. Группы трендов это не объекты и поэтому нельзя написать в скрипте например так: TrendGroup1.ID. Но даже если бы это было возможно, то для универсального скрипта пришлось бы сначала формировать имя группы, например подставляя тег объекта, вот так:
Код: pascal
Name := 'TrendGroup' + intToStr(Object.Tag); 

затем искать группу по этому имени группу и извлекать её ID. Т.е. в любом случае для универсального перехода в группу из окна нам придется где-то взять номер группы (в примере выше этот номер берется из Тега объекта). Но ведь и сейчас нам ничего не мешает хранить в теге ID нужной группы. Т.е. при открытии окна в его свойство Тег (или свойство Тег какого-то объекта окна) подставлять ID группы в которую нужно выполнить переход из данного окна. По нажатию на кнопку перехода в группу брать тег и переходить в указанную группу.

Рассмотрим пример. В проекте есть:
  • две группы трендов. ID первой группы = 1, ID второй группы = 8;
  • две кнопки Button1 и Button2. Тег первой кнопки устанавливаем = 1, а тег второй = 8;
  • универсальное окно с кнопкой Button3 для перехода в группу трендов;
На кнопки Button1 и Button2 ставим универсальный скрипт который показывает окно и передает в тег окна свой тег (кнопки). А по нажатию на Button3 пишем переход в группу с ID равным тегу окна. Готово.

Но здесь нам может просто не хватить тегов. Насколько нам известно у вас на кнопках открытия универсального окна уже выставлены теги и выставить им ещё и ID нужных групп просто некуда. Это так? Тогда нужно подумать куда вписать идентификаторы групп.

596039

#182
Да все правильно, сегодня попробовал реализовать все следующим образом:

Код: pascal
begin
  if not (Sender is TM_Image) then Exit;
  Field_Speed_P.Variable  := GetVariableByName('Speed_P_' + IntToStr(Sender.Tag));
  Field_Speed_V.Variable := GetVariableByName('Speed_V_' + IntToStr(Sender.Tag));
  Field_Three_Way_Heat.Variable := GetVariableByName('Three_Way_Heat_' + IntToStr(Sender.Tag));
  Field_Set.Variable := GetVariableByName('Set_' + IntToStr(Sender.Tag));
  Field_Temp_Room.Variable := GetVariableByName('Temp_Room_' + IntToStr(Sender.Tag));
  Field_Temp_Air.Variable := GetVariableByName('Temp_Air_' + IntToStr(Sender.Tag));
  Field_Temp_Water.Variable := GetVariableByName('Temp_Water_' + IntToStr(Sender.Tag));
  Image_Mode_Cool.Variable := GetVariableByName('Mode_' + IntToStr(Sender.Tag));
  Image_Mode_Heat.Variable := GetVariableByName('Mode_' + IntToStr(Sender.Tag));
  Button_Mode.Variable := GetVariableByName('Mode_' + IntToStr(Sender.Tag));
  Image_Filtr1.Variable := GetVariableByName('Status_P_' + IntToStr(Sender.Tag));
  Image_Filtr2.Variable := GetVariableByName('Status_P_' + IntToStr(Sender.Tag));
  Image_Vent_P.Variable := GetVariableByName('Status_P_' + IntToStr(Sender.Tag));
  Image_Vent_V.Variable := GetVariableByName('Status_V_' + IntToStr(Sender.Tag));
  Image_Trend.Variable := GetVariableByName(IntToStr(Sender.Tag));                             //Присваиваем значение переменной
  Text_PV.Text := 'ПВ_' + IntToStr(Sender.Tag);

  case Image_Vent_P.AsInt  of
     0, 2, 4..7: Image_Vent_P.AnimSpeed := 0;
     1, 3: Image_Vent_P.AnimSpeed := GetVariableByName('Speed_P_' + IntToStr(Sender.Tag)).AsInt;
  end;

  case Image_Vent_V.AsInt  of
     0, 2, 4..7: Image_Vent_V.AnimSpeed := 0;
     1, 3: Image_Vent_V.AnimSpeed := GetVariableByName('Speed_V_' + IntToStr(Sender.Tag)).AsInt;
  end;

   if GetVariableByName('Status_P_' + IntToStr(Sender.Tag)).AsInt = 3 then
   begin
    Image_Filtr2.Visible := True;
    Image_Filtr1.Visible := False;
    Text1_Filtr.FlashColor := clRed;
    Text2_Filtr.Text := 'Требует замены';
    Text2_Filtr.FlashColor := clRed;
   end else
   begin
    Image_Filtr2.Visible := False;
    Image_Filtr1.Visible := True;
    Text1_Filtr.FlashColor :=clNone;
    Text2_Filtr.Text := 'В работе';
    Text2_Filtr.FlashColor :=clNone;
   end;
end.


А в скрипт привязанный к кнопке трендов подставляем значение переменной:
Код: pascal
var
  Name : String;
  Trend : TM_Variable;
begin
  Name := GetClientName;
  Trend := GetVariableByName('Image_Trend');
  GoToTrendsGroupClient (Name, Trend.Value + 3);      //Подставляем нужный номер в идентификатор
end.

596039

Не совсем понимаю почему не работает. Но эта схема не совсем универсальна.Например при масштабировании проекта придется добавлять новые универсальные окна, так как нет возможности присваивать идентификаторы вручную, соответственно строка: "GoToTrendsGroupClient (Name, Trend.Value + 3);" будет работать только в том случае если идентификаторы идут по порядку.

Simple-Scada

#184
В этой ситуации предлагаем такой способ: у кнопки которая вызывает универсальное окно в Редакторе задействуем свойство Тег для подстановки в универсальное окно соответствующих переменных, как у вас это уже сделано. Но! Помимо этого задействуем ещё свойство Подсказка. Оно имеет строковый тип, но подойдет нам. И в Редакторе вписываем в Подсказку ID группы трендов в которую будет осуществлен переход из универсального окна, вызванного этой кнопкой. В этом случае в ваш скрипт с подстановкой значений добавится ещё одна строка, вот так:

Код: pascal
begin
  if not (Sender is TM_Image) then Exit;

  { записываем в Тег кнопки ID-группы в которую нужно будет перейти }
  ButtonToTrend.Tag := StrToInt(Sender.Hint);       // эта строка
  
  { далее код Вашего скрипта без изменений }
  Field_Speed_P.Variable  := GetVariableByName('Speed_P_' + IntToStr(Sender.Tag));
  Field_Speed_V.Variable := GetVariableByName('Speed_V_' + IntToStr(Sender.Tag));
  ...

в данном случае "ButtonToTrend" это имя кнопки трендов, которая находится в универсальном окне и по нажатию на которую нужно перейти в группу трендов. Тогда скрипт OnClick для этой кнопки будет таким:

Код: pascal
begin
  GoToTrendsGroupClient (GetClientName, Sender.Tag);
end.

Что скажете на счет такого решения?

toreto

Здравствуйте!!
Помогите с таким вопросом, имеется некий счетчик который постоянно и неравномерно увеличивается, нужно посчитать количество за час и сделать записи каждого часа в БД.

Simple-Scada

Здравствуйте.

Нужно получить число на которое увеличился счетчик за час? Например счетчик за час выдает последовательно такие значения: 100, 101, 102, 130, 131. Тогда результат должен быть: 31?

toreto

Примерно что то такое. Точнее- опрашиваются показания электроэнергии из счетчика, и нужно сделать почасовку потребления.

Simple-Scada

#188
Если так, то можно просто запоминать в начале каждого часа текущее значение и записывать измеренное за прошедший час. Для корректной работы нужно три виртуальных переменных:
  • vrInit (тип данных Boolean, можно без шкалы);
  • vrByHour (тип данных тот же, что и у переменной счетчика, шкала должна быть достаточно большой). Для хранения результата за прошедший час;
  • vrStartCount (тип данных тот же, что и у переменной счетчика, шкала должна быть достаточно большой). Хранит значение счетчика на начало часа;
Далее создаем скрипт с типом события "Прошел час" и пишем такой код:

Код: pascal
begin
  if vrInit.AsBool then
  begin
    { получаем значение, накопленное за прошедший час }
    vrByHour.Value := Int1.AsInt - vrStartCount.AsInt;
    // ... здесь можно разместить код сохранения значения за прошедший час в БД, или файл
    vrStartCount.Value := Int1.AsInt;
  end else
    begin
      vrInit.Value := True;
      vrStartCount.Value := Int1.AsInt;
    end;
end.

При этом расчеты появятся в переменной vrByHour только после того, как пройдет один полный час после старта сервера скады. И соответственно после перезапуска сервера также придется ждать один полный час, чтобы скада показала накопленное значение за этот час.

Morozbl4

Здравствуйте!
Есть булевая переменная i, которая отвечает за реле, время работы задается ручками условно от 1 до 5 секунд.
Необходимо перед выключением считать значение переменной P с контроллера и присвоить это значение виртуальной переменной Pmax.
При использовании while  do все уходит в бесконечный цикл и зависает...
If тоже не работает....
Помогите советом, пожалуйста.

Simple-Scada

Здравствуйте, Morozbl4.

Есть переменные:
  • vrI - переменная реле, boolean;
  • vrP - переменная которую нужно считать перед выключением реле;
  • vrPmax - виртуальная переменная в которую будем читать vrP;
Создаем в проекте новый объект, неважно какой, например простой Текст (TM_Text). В свойствах выбираем ему "Переменная - vrI". Теперь он связан с переменной vrI. Переходим в событие OnDataChange и пишем такой скрипт:

Код: pascal
procedure Text1_OnDataChange(Sender: TM_Control);
begin
  // если реле выключается, то записываем vrP в vrPmax
  if vrI.AsBool = False then 
    vrPmax.Value := vrP.Value;
end.

Если у Вас в проекте уже есть объект, который связан с vrI, то используете его вместо Текста из примера выше.

В ближайшем будущем появится возможность создавать OnDataChange-скрипты без связи с каким-либо объектом и тогда можно будет сразу писать OnDataChange-скрипт, без объекта.

Morozbl4


Dim

Здравствуйте. Есть тренд для булевых переменных. Как можно сделать чтоб тренд записывался только когда переменная  =1 а когда будет равняться 0 записи не будет?

Simple-Scada

Здравствуйте.

По событию OnDataChange для данной boolean-переменной написать такой скрипт:

Код: pascal
begin
    vrBool.Archived := not vrBool.AsBool;
end.

Здесь vrBool это имя переменной по которой ведётся тренд. Правда непонятно для чего так делать, ведь в этом случае в тренд попадут только значения равные 1.

Dim

Когда сделаю выложу скриншот. А как толщину линии добавить