В предыдущей части мы завершили создание визуализиции задвижки и создали простейший скрипт, имитирующий ее поведение.
У нас есть одна панель под названием 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. При этом система автоматически определит присутствие $-параметров и предложит подставить вместо формального значения — фактическое.
Зададим имя клапана, вместо $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/
Добавить комментарий