Самоучитель по WinCC OA. Часть 4. Повторное использование объектов. $-параметры

от автора

В предыдущей части мы завершили создание визуализиции задвижки и создали простейший скрипт, имитирующий ее поведение.

У нас есть одна панель под названием Flap, которая отображает и шлет команды для одной задвижки — Flap1. Именно такая точка данных указана во всех скриптах этой панели. Возникает закономерный вопрос — что делать, если задвижек не одна? И даже не две. А несколько десятков, сотен и даже тысяч (для распределенной системы WinCC OA и несколько миллионов сигналов не помеха, смотрим на Большой Андронный Коллайдер, где применяется именно это система, и завидуем).

Очевидный вариант — создать несколько десятков, сотен и тысяч панелей, где каждая точки данных приведена явно, отметаем — долго, хлопотно и грозит огромными трудозатратами в случае малейших изменений, неизбежных во время ПНР.

Другой вариант, но не единственный, создание шаблона на основе имеющейся панели. Создадим копию имеющейся панели Flap, для чего выберем пункт меню Panel → Save Panel As. Зададим имя Panel_ref.pnl (окончание _ref подразумевает reference, т.е. ссылку, или, если будет угодно, шаблон)

Откроем панель Flap_ref (она и так должна быть открытой после сохранения). Отредактируем скрипты панели, выбрав в меню Edit → Edit Panel Scripts. Откроется окно, содержащее все скрипты всех графических примитивов данной панели.

Для задвижки у нас создан собственный тип точки данных, и такие вещи, как положение или команда открытия в любом скрипте будут одинаковыми для всех задвижек. Различаться будут только имена задвижек, т.е. имена точек данных: Flap1, Flap2 и Flap3 в нашем простом случае. Для того, чтобы создать шаблон необходимо заменить имя задвижки, Flap1 на конструкцию, содержащую $-параметр (он так и называется в документации «доллар-параметр»). Проще все замены выполнять посредством Find&Replace в редакторе. Скрипты теперь выглядят так.

──────────────────────────────────────────────────────────────────────────────────────────────────── ─// [RECTANGLE3] [3] - [Initialize] // SimpleCtrlScriptStart {invalid} main() {   EP_setRotation(); }  void EP_setRotation() {   dyn_errClass err;    if( !dpExists( "System1:" + $dp + ".Inputs.Position:_online.._value") )   {     setValue("", "color", "_dpdoesnotexist");     return;   }    dpConnect("EP_setRotationCB",             "System1:" + $dp + ".Inputs.Position:_online.._value");   err = getLastError();   if (dynlen(err) > 0)     setValue("", "color", "_dpdoesnotexist");  }   void EP_setRotationCB(string dp1, int iNewValue) {   float MIN_VALUE = 0;   float MAX_VALUE = 90;   float MIN_ROTATION = 0;   float MAX_ROTATION = 90;    float fRotation;   fRotation = ( 1.0 * (MAX_ROTATION - MIN_ROTATION) / (MAX_VALUE - MIN_VALUE)) *               (iNewValue - MIN_VALUE) + MIN_ROTATION;   if (fRotation > MAX_ROTATION) fRotation = MAX_ROTATION;   else if (fRotation < MIN_ROTATION) fRotation = MIN_ROTATION;    setValue("", "rotation", fRotation); }  // SimpleCtrlScript {EP_setRotation} // DP {System1:" + $dp + ".Inputs.Position} // DPConfig {:_online.._value} // DPType {int} // PVSSRange {0} // Min {0} // Max {90} // MinRotation {0} // MaxRotation {90} // SimpleCtrlScriptEnd {EP_setRotation} ════════════════════════════════════════════════════════════════════════════════════════════════════ ─// [PUSH_BUTTON1] [4] - [Clicked] main(mapping event) {   dpSet("System1:" + $dp + ".Commands.Open", 1, "System1:" + $dp + ".Commands.Close", 0); } ════════════════════════════════════════════════════════════════════════════════════════════════════ ─// [PUSH_BUTTON2] [5] - [Clicked] main(mapping event) {   dpSet("System1:" + $dp + ".Commands.Open", 0, "System1:" + $dp + ".Commands.Close", 1); } ════════════════════════════════════════════════════════════════════════════════════════════════════ 

Было:

System1:Flap1.Inputs.Position:online..value

Стало:

System1:» + $dp + «.Inputs.Position:online..value

Строка, которая ранее содержала непосредственно элемент точки данных, теперь формируется из первой постоянной части (System1), к которой добавляется $dp, после чего добавляется вторая постоянная часть, которая так же не зависит от точки данных, т.е. — от конкретной задвижки. Знак + подразумевает объединение строк. Сами строки в данном случае заключены в кавычки. В явном виде такую панель использовать, разумеется, не получится. Необходимо задать подстановку для $dp (Flap2, например) при вызове этой панели.

Используя метод аналогии, можно сравнить $-параметры с формальными и фактическими параметрами функции в любом языке программирования. При вызове функции мы всегда должны задавать фактические параметры, значения которых заменят формальные, и функция отработает.

Теперь создадим новую панель. Пусть она называется Flaps. Сделаем новую панель чуть побольше.

Далее необходимо перетащить мышью из дерева проекта панель Flap_ref на рабочее поле открытой панели Flaps. При этом система автоматически определит присутствие $-параметров и предложит подставить вместо формального значения — фактическое.

Drag'n'drop
Drag’n’drop

Зададим имя клапана, вместо $dp укажем Flap1. Нажмем на кнопку «Save and Run in QuickTest Mode» и убедимся, что клапан 1 реагирует на нажатия кнопок Open и Close — то есть, открывается или закрывается. Если клапан вдруг не реагирует на команды, посмотрите состояние контрол-менеджера, добавленного в предыдущей части, он может быть остановлен (тогда его надо, разумеется, запустить, или просто перевести режим запуска из ручного в автоматический, чтобы каждый раз не отвлекаться).

Все работает
Все работает

Добавим точно так же панель для Flap2

Проверяем. Первый клапан работает (управляется), второй- не работает. Почему? Все просто, созданная вчера модель (в виде скрипта) управляет всего лишь одним клапаном Flap1. Остальные клапаны в модели не описаны.

Второй клапан не работает
Второй клапан не работает

Доработаем имеющуюся модель для того, чтобы она управляла и вторым клапаном тоже. Модифицируем быстро, но неправильно, путем копи-паста. Создаем еще две функции dpConnect и две разных callback-функции, переименовываем первую callback-функцию. В итоге получается такой код.

Не забываем перезапустить Control Manager этого скрипта (тот, что с опцией «-num 2»). После модификации модели проверяем изменения и видим, что оба клапана управляются независимо.

В связи с тем, что на DPE Position у нас «натравлен» конфиг с функцией, третий клапан на экран пока не выносим (собственно, я его и в модель-то напрасно внес).

ссылка на оригинал статьи https://habr.com/ru/post/530890/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *