Автор: Кангин В.В. Кангин М.В. Ямолдинов Д.Н.
Теги: языки программирования комбинированные (непрерывно дискретные) электронные вычислительные машины и устройства цифровые интегрирующие машины программирование автоматизация учебное пособие компьютерные технологии язык программирования delphi
ISBN: 978-5-9729-0319-1
Год: 2019
«яг curLe«4<r-l-a*tL(ji, I., и-»:
it (ссг« ** цм,
С
flprlvcf(»г4»гт, Failed to create СШи «ewwcM^VrJ;
•rtt£tXlT fAJUitl);
) . ’ uJbU-H
code • csrlKedyHietcpMcaml CURLORfBtRHOftmtFtM,
arrortuifer);
1Г (e«U • CUfciX.tt)
fpxircf(»t4arr, Failed to »«t error buffer ,
cod*);
r<tum tales;
)
cod* car I easy uu^com, ОШН URL. er I >5
it (<«й p aiw.w)
(
fpxietCCaWorr, 'Felled to »«t URL [М]\п’и КПИрП-
«>;
wtnm Eolia;
)
coda carl eaiy^i.etcpt(c>Qa», CUtLOCT ГйШМьОСЛТЭДМ,
u>;
it (coda I» <URl£
f|irlT/rf(fCaUrt. ’Felled to Mt T*4ir«T «Ча1<*ч
ercortuttar).
return fiUi
> . .1 ЛеШй ЙТДЮ1 JewKll/ \
code • cwl_Miy_ufco<(«gm, CLMUFT.beiTlFUWCTICM.
at st er);
It {coda I* tuftUEjM)
£t*rl*<t{«tdei£. ‘Failed to lit aticot
«xrosdultvz); ... - . , i\ -, , ,, 1к
м«вгн falto;
code • сшl_e*iy_•♦«*<(tend, O№l0PT^WTWAXA»
Abetter);
St {coda I- ОЖК Otf)
(
Qcmrext «голгагс • (Gocrtevr ^ywndCutrorr
И (CfrPAKit(chrx ')m*o TITLE ))
• ‘Л
coTtaot-laddTltla - trw;
1
oLuitoa-гь,
mim :wxf#J ।
7/
// llbial and (wA callback IixnctlOn
//
«title void fndf taae-*(»i31d ••rtldCcr+.aoit,
conit nLChix *тшм)
(
Gw»ta*t *rontW4t • (Gorrtaxt "}nreiOCent-r^t_
If (Omif((cb&r *)n*»er TnU’))
ecet-tat->*ddTitlv • faLaa.
)
// Teat hindllr^ h«Lp<-x [enctioo
7/
ititlc ha«dl«Chrr xct are. £ Contort ’ccrtcrt,
(Ontr; wlChir
Lfrt la*^th)
<
SC («мпarc x*dJTitl»)
ем«Д>ХНк. 4JV«*dl(chi£ ‘Jtfrar-b, LadfMl).
>
П
f/ llboail rCDtTA caLlbajck tiKtlon
/Л r.
static odd Character»(void a-anldCc*4,eat.
const a I Ch xt •chxc»_
1HC
(
• rant*rt (Cor»C4<t *y»Q(dCcm*xt-
hirvSLeD-Axact«ri(cort«Al char» , Lengt-h);
>
ititle odd edJtaCwid •vddCarttoL.
ccmt xSlChar •chari,
iangth)
В. В. Кангин, M. В. Кангин, Д. H. Ямолдинов
РАЗРАБОТКА
SCADA-СИСТЕМ
«Ин фра -И мженерия»
В. В. Кангин, М. В. Кангин, Д. Н. Ямолдинов
РАЗРАБОТКА
SCADA-CI/ICTEM
Учебное пособие
Москва Вологда
«Инфра-Инженерия»
2019
УДК 004.438Delphi
ББК 32.973.3
К19
Кангин, В. В.
К19 Разработка SCADA-систем : учебное пособие / В. В. Кангин,
М. В. Кангин, Д. Н. Ямолдинов. - Москва ; Вологда : Инфра-
Инженерия, 2019. - 564 с. : ил., табл.
ISBN 978-5-9729-0319-1
Даны рекомендации по проектированию SCADA-системы с исполь-
зованием среды визуального программирования Delphi. Приведен обзор
существующих SCADA-систем с анализом принципов их работы. Рассмо-
трены возможности SCADA-системы как инструмента для просмотра те-
гов. Освещены вопросы организации распределенных систем управления
с развитым диспетчерским уровнем.
Для программистов, системных интеграторов, специалистов, за-
нимающихся разработкой распределенных систем управления, научных
работников, аспирантов и студентов вузов соответствующих специально-
стей.
УДК 004.438Delphi
ББК 32.973.3
ISBN 978-5-9729-0319-1 © Кангин В. В., Кангин М. В., Ямолдинов Д. Н., 2019
© Издательство «Инфра-Инженерия», 2019
© Оформление. Издательство «Инфра-Инженерия», 2019
ОГЛАВЛЕНИЕ
ВВЕДЕНИЕ..................................................5
ГЛАВА 1.
SCAD А-системы в компьютерных распределенных
системах управления.......................................9
1.1. Обзор существующих S С ADA-систем..................9
1.2. ОРС-стандарт обмена информацией SCADA-систем и ПЛК.31
1.3. Функции, выполняемые S С ADA-системами.............36
1.4. Структура стандарта ОРС..........................43
1.5. Структура компьютерной распределенной системы
управления и организация программного обеспечения
диспетчерского уровня.................................51
1.6. Fastwel PlcNet ОРС Server — ОРС-сервер
для сетей PLCNET......................................57
1.7. Работа с ОРС-сервером Fastwel PlcNet ОРС Server..74
ГЛАВА 2.
Организация взаимодействия программного обеспечения
диспетчерского и контроллерного уровней в компьютерных
распределенных системах управления.......................81
2.1. Структура компьютерной распределенной системы управления
с одним узлом на диспетчерском уровне..................81
2.2. Простейший просмотрщик тегов для промышленной
сети PLCNET...........................................83
2.3. Просмотрщик тегов в виде столбчатой диаграммы....97
2.4. Просмотрщик тегов в виде круговой диаграммы
со стрелкой..........................................131
2.5. Просмотрщик тегов в виде круговой диаграммы.....158
2.6. Использование мультипликации в системах
визуализации информации..............................187
2.7. Сетевой лазерный тир............................230
2.8. SCADA-система для робота IRON BURATINO..........296
ГЛАВА 3.
Организация взаимодействия программного обеспечения
компьютеров диспетчерского уровня
распределенной системы управления.......................347
3.1. Структура компьютерной распределенной системы
управления с многоузловым диспетчерским уровнем........347
3
РАЗРАБОТКА SCADA-СИСТЕМ
3.2. Назначение и организация объекта автоматизации....352
3.2.1. Модуль AddUnit..............................352
3.2.2. Модуль MainUnit.............................375
3.2.3. Практическая работа с объектом автоматизации.398
3.2.4. Модуль NDgrServer TLB.......................402
3.3. Назначение и организация ОРС-клиента..............405
3.3.1. Функции, выполняемые ОРС-клиентом...........405
3.3.2. Хранение данных в ОРС-клиенте...............406
3.3.3. Обработка данных в ОРС-клиенте..............412
3.3.4. Работа с ОРС-клиентом.......................532
3.3.5. Взаимодействие ОРС-сервера, объекта автоматизации
и ОРС-клиента................................545
ЗАКЛЮЧЕНИЕ....................................550
БИБЛИОГРАФИЯ..................................551
ПРИЛОЖЕНИЯ....................................552
Приложение 1. Список сокращений...............552
Приложение 2. Глоссарий.......................554
4
ВВЕДЕНИЕ
В настоящее время наблюдается качественный скачок в разви-
тии систем управления технологическим оборудованием и техноло-
гическими процессами. Системы управления стали децентрализо-
ванными, распределенными. Таким образом, в настоящее время мож-
но говорить о распределенных системах управления (РСУ).
Промышленные и локальные сети представляют собой физиче-
скую среду, на базе которой реализуются РСУ. РСУ в классическом
виде представляет двухуровневую структуру. На нижнем уровне этой
структуры находятся контроллеры — устройства, осуществляющие
непосредственное управление технологическими процессами в ре-
альном времени. Контроллер должен решать задачу управления бы-
стро, в темпе протекания технологического процесса.
Производством контроллеров занимается большое количе-
ство фирм как в России, так и за рубежом. Контроллеры подразде-
ляются на моноблочные (компактные), модульные и PC-base конт-
роллеры.
Значительное развитие получили PC-base контроллеры, пред-
ставляющие, по сути, IBM PC, но выполненные в миниатюрном
промышленном исполнении. По своим техническим характеристи-
кам они приспособлены для работы в условиях улицы, цеха, склада.
Именно один из этих контроллеров, а именно ADAM-5510 фирмы
Advantech (Тайвань), будет рассматриваться в данной работе.
На верхнем уровне РСУ расположены удаленные компьютеры
(рабочие станции), позволяющие выполнять следующие задачи:
- сбор данных о параметрах технологического процесса, их об-
работка и архивирование принятой информации;
- визуализация информации о ходе технологического процес-
са, сигнализация о предаварийных и аварийных ситуациях;
- формирование сводок, журналов, отчетов и т. д.;
- формирование команд оператора, направленных на измене-
ние параметров настройки и режимов работы контроллеров;
- автоматическое управление ходом технологического процес-
са (только в ряде случаев и для решения задач невысокого
быстродействия).
5
РАЗРАБОТКА SCADA-СИСТЕМ
Рабочие станции верхнего уровня представляют собой автома-
тизированные рабочие места (АРМ) производственного персонала,
обслуживающего технологический процесс: операторы, технологи,
наладчики, диспетчеры и т. д. Верхний уровень РСУ называют дис-
петчерским или операторским уровнем.
Диспетчерский уровень представлен персональными компью-
терами (ПК), рабочими станциями, промышленными компьютерами
ит. д.
Контроллеры, решая задачу непосредственного управления тех-
нологическим оборудованием, принимают сигналы с датчиков и вы-
дают управляющие сигналы на исполнительные механизмы. Одно-
временно с этим они решают еще одну важную задачу — передают
информацию о состоянии технологического процесса на компьютеры
верхнего диспетчерского уровня. В ряде случаев контроллеры могут
обмениваться данными и между собой. Промышленная сеть и есть та
физическая среда, по которой происходит обмен информацией между
активными компонентами (узлами) РСУ. Таким образом, узлом в про-
мышленной сети является контроллер.
Каждый технологический параметр представлен в сети в виде
некоторой переменной — тега, и характеризуется величиной, каче-
ством передачи (приема) по сети, типом и т. д.
Выделение в РСУ двух уровней позволяет говорить о программ-
ном обеспечении (ПО) для верхнего и для нижнего уровня. Есте-
ственно, что ПО для верхнего и нижнего уровней РСУ в значитель-
ной степени различаются.
ПО для нижнего (контроллерного) уровня представляет собой
программы, загруженные во флеш-память каждого контроллера,
и выполняющиеся циклически. Для программирования контрол-
леров можно использовать языки высокого уровня, например C++,
но в настоящее время широко используются специализированные
языки программирования по стандарту IEC 61131-3.
К таким языкам, принадлежащим к группе языков Functional
Block Diagrams (FBD) — функциональных блоковых диаграмм, от-
носится язык UltraLogik, использующийся для программирова-
ния контроллеров ADAM-5510. Этот язык позволяет легко выпол-
нить проектирование управляющих программ высокой степени слож-
ности.
6
ВВЕДЕНИЕ
Какие бы алгоритмы не реализовала управляющая программа
контроллера, важно, чтобы она еще передавала определенную нуж-
ную информацию в сеть. В UltraLogik это делается довольно просто.
Достаточно той или иной переменной (параметру технологического
процесса, состоянию того или иного датчика, управляющему сигна-
лу и т. д.) присвоить статус «сетевая», как она гарантированно будет
периодически передаваться контроллером в сеть.
ПО верхнего уровня реализуется в виде SCADA-системы
(Supervisory Control and Data Acquisition — система сбора данных
и оперативного диспетчерского управления). Задачи, которые выпол-
няют SCADA-системы, были обозначены выше, но центральной яв-
ляется задача по приему тегов из сети. Для этих целей используются
специальные приложения (программы), называемые ОРС-серверами.
ОРС-сервер считывает значения тегов из сети и передает их приложе-
нию (программе) — клиенту. SCADA-системы являются клиентами
ОРС-серверов.
Разработкой SCADA-систем занимается ряд фирм (см. главу 1).
Каждая SCADA-система имеет две составляющие:
- инструментальная система (SCADA-пакет), с помощью ко-
торой можно разработать SCADA-систему нужного назначе-
ния;
- исполнительная часть — приложение, полученное в резуль-
тате работы инструментальной системы, устанавливаемое на
рабочей станции диспетчерского уровня РСУ.
Фирмы — разработчики SCADA-систем поставляют именно
инструментальную систему. Анализ существующих SCADA-систем
показывает, что каждая из них представляет собой специализиро-
ванный пакет программ, объединенный специфическим интерфей-
сом, особенностями использования, идеологией организации и т. д.
Все это затрудняет переход от одной SCADA-системы к другой.
Высокая стоимость существующих SCADA-систем, отсутствие
качественной технической документации, избыточность, за кото-
рою приходится платить пользователю, делают процесс внедрения
SCADA-систем в производство весьма непростым мероприятием,
которое под силу лишь «богатым» предприятиям, как правило, из
сферы добычи прочих полезных ископаемых. Рядовым предприяти-
ям машиностроительного профиля такие «игрушки» не по карману.
7
РАЗРАБОТКА SCADA-СИСТЕМ
Да и нет подготовленных кадров для решения задач проектирования
SCADA-систем с помощью SCADA-пакетов. Эти задачи выполняют,
как правило, специализированные фирмы — системные интеграто-
ры, услуги которых тоже очень недешевы.
Однако пессимизм в данном вопросе можно развеять, если по-
нять, что SCADA-систему любого уровня сложности и назначения
можно спроектировать и без дорогостоящих услуг фирм — раз-
работчиков SCADA-систем. Проектирование легко выполнить с по-
мощью таких программных средств, как Delphi, Visual C++, VBA.
Они имеют в своем составе все необходимые средства для работы
с ОРС-серверами, графикой, мультипликацией, базами данных и т. д.
Именно тому, как спроектировать свою собственную простую,
но достаточно эффективную SCADA-систему, используя среду визу-
ального программирования Delphi, посвящена эта книга.
В первой главе выполнен обзор существующих SCADA-си-
стем, дан их анализ. Приводятся сведения о принципе работы ОРС-
серверов, их взаимодействии с другими приложениями-клиента-
ми. Рассмотрены правила работы с ОРС-сервером фирмы Fastwel
(Fastwel PLCNet ОРС Server).
Вторая глава посвящена проектированию просмотрщиков тегов,
представляющих информацию в виде таблицы, столбчатых и круго-
вых диаграмм, круговых диаграмм со стрелкой. Рассмотренные здесь
SCADA-системы названы просмотрщиками тегов, поскольку при их
разработке ставилась лишь задача приема тегов из сети и визуализа-
ции их значений в табличной или графической форме.
В третьей главе рассматриваются вопросы организации РСУ с
развитым диспетчерским уровнем. Здесь особое внимание уделено
вопросу передачи информации с мастера сети на удаленные компью-
теры и рабочие станции сети Ethernet.
Приложения содержат список сокращений, глоссарий.
Книга предназначена для программистов, системных интеграто-
ров, специалистов, занимающихся разработкой РСУ, научных работ-
ников, аспирантов и студентов вузов соответствующих специально-
стей.
8
ГЛАВА 1.
SCADA-системы в компьютерных распределенных
системах управления
1.1. Обзор существующих SCADA-систем
Современные распределенные системы управления (РСУ)
имеют территориальное и функциональное распределение систем
сбора данных и управления. Контроль за ходом технологического
процесса, состоянием агрегатов и машин осуществляется операто-
ром с автоматизированного рабочего места оператора (АРМ опе-
ратора) или операторской станции, установленной в операторском
помещении. При необходимости установки АРМ оператора в цеху
используются промышленные рабочие станции со встроенной кла-
виатурой, выполненные в пыле-, влагозащищенном исполнении.
Представление данных о ходе технологического процесса
в реальном масштабе времени, визуализация процессов в виде
мнемосхем, составление отчетов и графиков, сигнализация откло-
нений параметров и другие функции осуществляются с помощью
специального программного обеспечения, которое называется
SCADA-системой.
SCADA-система (Supervisory Control And Date Acquisition —
система сбора данных и оперативного диспетчерского управления)
представляет собой универсальное многофункциональное про-
граммное обеспечение (ПО) систем верхнего уровня автоматизиро-
ванных систем управления технолгическими процессами (АСУ ТП).
Это ПО позволяет оперативному персоналу наиболее эффективно
управлять технологическим процессом и контролировать его про-
текание. По мере развития программных и аппаратных средств на-
блюдается применение SCADA-систем и на нижнем, контроллерном
уровне.
Основные функции, выполняемые большинством SCADA-
систем:
1. Сбор данных о параметрах процесса, поступающих от кон-
троллеров или непосредственно от датчиков и исполнитель-
ных устройств: значения температуры, давления, положе-
ние клапана или вала исполнительного механизма и т. д.
9
РАЗРАБОТКА SCADA-СИСТЕМ
2. Обработка и хранение (архивирование) полученной ин-
формации. Под обработкой информации понимается вы-
полнение функций фильтрации, нормализации, масштаби-
рования, линеаризации и других для приведения данных
к нужному формату
3. Графическое представление информации о ходе технологи-
ческого процесса в цифровой, символьной или иной форме.
Это может быть динамизация значений переменных, пред-
ставление значений переменных в виде графиков в функции
времени (трендов), гистограмм и другое.
4. Сигнализация в предаварийных и аварийных ситуациях об
изменениях хода технологического процесса в виде систе-
мы алармов. При этом может осуществляться регистрация
действий обслуживающего персонала в аварийных ситуа-
циях.
5. Формирование сводок, журналов и других отчетных доку-
ментов о ходе технологического процесса на основе инфор-
мации, собранной в архивах.
6. Формирование команд оператора по изменению параметров
настройки и режима работы контроллеров, исполнитель-
ных устройств: пуск-останов, открытие-закрытие и другие
функции.
7. Автоматическое управление ходом технологического про-
цесса в соответствии с имеющимися в SCADA-системах
алгоритмами управления: ПИ-, ПИД-регулирование, пози-
ционное, нечеткое регулирование и т. д. Данные функции
рекомендуется использовать для решения задач невысокого
быстродействия.
Таким образом, SCADA-пакеты являются мощным инстру-
ментом для разработки ПО верхнего уровня АСУ ТП — SCADA-
систем. При этом от разработчика не требуется обширных знаний
в области программирования на языках высокого уровня.
Наиболее распространенные на сегодняшний день SCADA-
системы для РСУ представлены в табл. 1.1.
Рассмотрим характеристики SCADA-систем, используемых
в РСУ.
ю
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
Таблица т.т
Наиболее распространенные SCADA-системы для РСУ
№ Наименование Фирма-производитель, страна
1. InTouch Wonderware, США
2. Genesis32 Iconics, США
3. iFIX Intellution, США
4. Trace Mode AdAstra, Россия
5. Real Flex В J Software Systems (BISS), США
6. Cimplicity GE Fanuc, США-Япония
7. WinCC Siemens, Германия
8. Citect CI Technology, Австралия
9. IMAGE Numpha Soft, Финляндия- Россия
10. MasterSCADA НнСАТ, Россия
11. VNS НнСАТ, Россия
12. КРУГ 2000 КРУТ, Россия
13. WizFactory PC Soft International Inc., США-Израиль
14. Elipse Windows Elipse Software LTD А, Бразилия
15. Genie 3.0 Advantech, Тайвань
16. MOSCAD Motorola. США
17. CKAT-M Центрпрограммсистем, Россия
18. КАСКАД АО Эл ар а, Россия
19. VIORD microSCADA ФИОРД, Россия
20. Phocus Jade Software
21. МИКСИС (MIKSVS) МИФИ, Россия
SCADA-система InTouch (Wonderware, США)
Программное обеспечение InTouch является объектно-
ориентированным человеко-машинным интерфейсом (HMI —
Human Machine Interface) для процессов сбора данных и управле-
ния. HMI позволяет контролировать объекты и системы и управлять
ими, используя графические объекты.
Основные функции HMI:
- отображение параметров объекта управления;
- отображение текущих и исторических трендов;
- отображение и регистрация аварийных сигналов.
Средства объектно-ориентированного проектирования позволя-
ют создавать динамические изображения, поддерживают их вращение,
дублирование, копирование, вставку, стирание и другие операции.
Анимационные связи поддерживают работу с дискретными,
аналоговыми и строковыми переменными, горизонтальными и вер-
тикальными движками и кнопками, а также связаны с размером и
цветом текста, его местоположением, вращением и мерцанием.
InTouch содержит полную библиотеку мастер-объектов (Wizard),
11
РАЗРАБОТКА SCADA-СИСТЕМ
включающую предварительно сконфигурированные вспомогатель-
ные средства — переключатели, ползунковые регуляторы, счетчики.
Возможно создание собственных мастер-объектов применительно
к конкретной системе.
Приложение Productivity Pack, являющееся дополнением к
InTouch, содержит библиотеку из более чем 2 000 мастер-объектов,
универсальные средства просмотра, рассчитанные на 200 файловых
форматов, генератор мастер-объектов и т. д.
InTouch позволяет организовать взаимодействие с другими
приложениями, используя следующие стандартные средства:
1. DDE-обмен (Dynamic Date Exchange — динамический обмен
данными). Большинство серверов ввода-вывода, например
контроллеры, поддерживают DDE-обмен для передачи дан-
ных в InTouch-приложение. Популярное приложение Excel
также использует DDE-механизм. Используя NetDDE, по-
ставляемый с InTouch, пользователь получает возможность
связи по DDE между задачами на разных персональных
компьютерах (ПК) через сеть. Поддерживается связь меж-
ду операционными системами (ОС) Windows, VNS и UNIX
с помощью протоколов NetBIOS, TCP/IP и DecNET, а также
через последовательный канал.
2. OLE-технологию (Object Linking and Embedding — включе-
ние и встраивание объектов). Используется для взаимодей-
ствия с другими пользовательскими приложениями.
3. ОРС-программы (OLE for Process Control — OLE для управ-
ления процессами).
InTouch 7.11, поддерживаемая ОС Windows, является одним из
компонентов интегрированного пакета программного обеспечения
для полной автоматизации производства FactorySuite 2000.
Компоненты FactorySuite используются на трех уровнях авто-
матизации:
- на контроллерном уровне (управление процессом с помо-
щью ПЛК, УСО, рабочих станций);
- на уровне SCADA-систем (супервизорное управление тех-
нологическим процессом);
- на уровне MES-систем (оперативно-диспетчерское управле-
ние процессом).
12
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
FactorySuite построен на открытых технологиях COM, DCOM,
ОРС, ActiveX. Он содержит большое число серверов ввода-вывода,
обеспечивающих связь с оборудованием, приборами и устрой-
ствами связи. Вся информация накапливается в реляционной базе
данных реального времени IndustrialSQL Server. За счет исполь-
зования протокола SuiteLink обеспечивается высокое быстродей-
ствие (запись около 40 000 параметров в секунду с частотой записи
до 1 мс), компактность хранения данных (двухмесячный архив из
4 000 параметров занимает около 2 Мбайт дискового пространства).
Industrial SQL Server использует возможности Microsoft SQL
Server, в том числе его возможности фильтрации, объединения
и обработки данных для удобства их запроса и выборки. Industrial
SQL Server может автоматически обновлять статистические данные
в виде сводных таблиц с заданной производительностью, фиксируя
средние, а также максимальные и минимальные значения параме-
тров.
Данные из SQL сервера в виде отчетов могут передавать-
ся путем Web-файла в Internet и далее удаленным пользователям,
а также через GSM-модем запрашиваться и передаваться потребите-
лям. Кроме IndustrialSQL Server в FactorySuite входят приложения-
клиенты FactoryOffice, предназначенные для создания текущих
и архивных трендов, графиков и таблиц.
Кроме объектно-ориентированной графики, анимационных
связей и библиотеки мастер-объектов, InTouch дает пользовате-
лям возможность удаленного доступа к источникам данных ввода-
вывода (например, Microsoft Excel) без необходимости создания
тега в локальной базе данных тегов.
Тег — это запись базы данных, содержащая информацию о па-
раметре процесса.
Другими функциями InTouch являются одновременная под-
держка многочисленных источников алармов (поддержка от 1 до
999 приоритетов алармов). Алармы могут быть выведены на экран,
записаны на диск и выведены на печать. Также InTouch позволяет
создавать исторические тренды и тренды реального времени с воз-
можностью одновременного отображения до 8 переменных-тегов.
Тренд реального времени поддерживает работу с четырьмя пе-
ременными. При этом каждая переменная читается из собственного
13
РАЗРАБОТКА SCADA-СИСТЕМ
файла. Возможен экспорт данных в Excel, файл данных или в канал
DDE. Кроме того, пользователь может генерировать отчеты напря-
мую из проекта InTouch путем прямого форматирования экрана, вы-
водить на печать или рассылать по электронной почте.
Благодаря наличию функции SPC (Statistical Process Control —
Статистическое управление процессом) InTouch предоставляет воз-
можность статистического управления процессом на уровне опера-
тора. Функции пакета поддерживают логические и математические
выражения. Пользователь может выводить на экран действительные
числа с одним знаком после запятой. Кроме того, пользователь мо-
жет описывать свои собственные функции с добавлением их в меню.
Система паролей InTouch предоставляет встроенную систему
доступа на 10 000 уровней, гарантирующую надежную защиту си-
стемы.
Проекты с использованием InTouch широко используются
в различных отраслях промышленности.
Пакет InControl — это система программирования и управле-
ния с открытой архитектурой реального времени, позволяющая соз-
давать архитектуру SoftPLC с заменой традиционного программи-
руемого логического контроллера (ПЛК) на ПК PC, подключенный
к устройствам ввода-вывода через локальные сети Profibus, Modbus
и другие.
InControl поддерживает языки релейной логики (LD), после-
довательных функциональных схем (SFC) и структурированного
текста (ST) по стандарту IEC 61131-3. Поддерживается технология
ActiveX (ПИ-, ПИД-регуляторы, нечеткая логика и т. д.). Также до-
пускается программирование с использованием традиционных язы-
ков программирования. Встроенный менеджер проектов позволяет
организовать приложения по проектам, редактировать все програм-
мы в рамках одного проекта, присваивать приоритеты на управле-
ние разным задачам.
InControl поддерживает различные промышленные интерфей-
сы и сети — Profibus, DeviceNet, Interbus, DDE, SDS, Internet и дру-
гие. Подобно другим компонентам FactorySuite InControl через на-
бор мастер-объектов интегрируется с InTouch.
Пакет InTrack — система управления производственны-
ми процессами: от закупки сырья, материалов и комплектующих
14
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
до выпуска готовой продукции. Различные схемы производствен-
ных процессов создаются в специальном графическом редакторе
и включают мастер-объекты, среди которых есть производствен-
ные цепочки, материальные ресурсы, продукты и т. д.
Таким образом, в рамках одной прикладной программы совме-
щаются функции SCAD А- и MES-системы (Manufacturing Execution
System — Производственная исполнительная система). Использо-
вание DDE-обмена и OLE-технологии позволяют организовать
связь с устройствами ввода-вывода, а также с системами верхнего
уровня MRP (Management and material Resource Planning — система
планирования ресуров предприятия). InTrack включает в себя, по-
добно InTouch, теги, текущие и исторические тренды, алармы, сце-
нарные функции и мастер-объекты. За счет встроенных функций от-
крывается возможность автоматизации задач учета, планирования
и диспетчеризации производства.
InBatch — гибкая система управления процессами дозирования
и смешивания в металлургической, химической, пищевой и других
отраслях промышленности. Имеется возможность моделировать
процессы, создавать рецепты и имитировать их исполнение, а так-
же управлять реальным процессом. InBatch интегрирован с InTouch,
что позволяет оператору вести мониторинг периодических процес-
сов дозирования и смешивания. Кроме того, InBatch имеет набор
функций для интеграции с ERP-системами (Enterprise Resource
Planning — система планирования производства), в том числе осу-
ществлять планирование сроков, материалов и производственных
результатов производственных процессов.
FactorySuite Web Server с помощью утилиты Application
Publisher выполняет функции преобразования созданных InTouch
приложений в вид, доступный для просмотра с любого удаленного
узла, и управления производственным процессом в режиме реаль-
ного времени через Internet и Intranet.
SCADA-система Genesis32 (Iconics, США)
Genesis32 состоит из 32-разрядных приложений для ОС
Windows, построенных в соответствии с технологией ОРС. В со-
став Genesis32 входит среда разработки и исполнения сценарных
процедур VBA (Visual Basic for Application), который входит
15
РАЗРАБОТКА SCADA-СИСТЕМ
в пакет MS Office 2000. Все программные компоненты Genesis32
поддерживают технологию ActiveX. В состав Genesis32 входят
следующие клиентские приложения: GraphWorX32, TrendWorX32,
AlarmWorX32 и ScriptWorX32. Данные приложения могут постав-
ляться как в составе комплекса Genesis32, так и отдельно.
В число дополнительных приложений и инструментальных
средств разработки входят: DateWorX32, Symbols32Library, ActiveX
ToolBox, WebHMI, ОРС-серверы и ряд других.
GraphWorX32 — программный пакет, предназначенный для
представления параметров технологического процесса на графи-
ческих мнемосхемах и представляющий собой полностью соответ-
ствующее спецификации ОРС клиентское приложение, основанное
на технологиях ActiveX и OLE. Экранные формы визуализации па-
раметров технологических процессов (мнемосхемы процесса) соз-
даются на основе встроенных средств рисования (библиотека эле-
ментов отображения) или управляющих элементов ActiveX других
производителей.
Возможна динамизация элементов изображения со временем
обновления графической информации 50 мс, встраивание графи-
ков TrendWorX32 и экранов AlarmWorX32, а также встраивание
в HTML-страницы и просмотр браузерами Internet (MS Internet
Explorer).
TrendWorX32 обеспечивает накопление текущих данных (па-
раметров), получаемых от серверов, и представление их в виде гра-
фических зависимостей от времени. Он также ведет архивацию
информации в базах данных с возможностью последующего извле-
чения и просмотра в виде трендов. Используются виды зависимо-
стей значений параметра от времени, логарифмическая зависимость
параметра от времени, гистограмма, зависимость одного параметра
от другого. К другим функциональным возможностям TrendWorX32
относятся:
- архивирование значений параметров в базе данных (БД)
MS Access, MS SQL Server, Oracle и Microsoft Date Engine
(MSDE) с помощью сервера архивации данных TrendWorX32
SQL Server;
- возможность одновременного просмотра текущих и архив-
ных данных;
16
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
- вывод графиков на печатающее устройство, сохранение от-
четов в формате HTML и т. д.
AlarmWorX32 — подсистема обнаружения аварийных и других
событий, связанных с отклонением параметров системы от заданных
значений. Основные функциональные возможности AlarmWorX32:
- обнаружение аварийных событий по признакам, определяе-
мым пользователем;
- оповещение персонала об обнаруженных отклонениях пара-
метров (дозвон по коммутируемым линиям связи, звуковой
сигнал, голосовое сообщение);
- анализ аварийных ситуаций и действий обслуживающего
персонала;
- запись информации об аварийных событиях в журнал
Windows и ряд других.
Сервер архивации событий AlarmWorX32 SQL Logger предна-
значен для приема сообщений о событиях от серверов ОРС Alarms
and Events и записи их в базу данных MS Access и MS SQL Server.
ScriptWorX32 — средство разработки и исполнения сценар-
ных процедур VBA, в том числе формирования отчетов и заданий.
К числу функциональных возможностей ScriptWorX32 относятся:
- ускорение разработки сценариев при помощи Мастера сце-
нариев;
- возможность компиляции сценариев в многопоточные би-
блиотеки динамической компоновки (DLL);
- диагностика текущих состояний сценариев;
- открытый интерфейс OLE Automation и другие.
DateWorX32 — ОРС-сервер для связи клиентских и серверных
компонентов. Функциональные возможности DateWorX32:
- централизация параметров процесса от множества серверов
ОРС в едином списке;
- оптимизация запросов множества клиентов ОРС к одним
и тем же параметрам в разных серверах ОРС;
- организация списка глобальных переменных с возможно-
стью выполнения арифметических, функциональных, логи-
ческих и других операций над ними.
WebHMI — средство просмотра графических мнемосхем про-
цесса в сетях Internet и Intranet. Данные могут быть представлены
17
РАЗРАБОТКА SCADA-СИСТЕМ
любому PC, на котором установлен браузер Microsoft Internet Explorer.
Кроме просмотра информации WebHMI обеспечивает возможность
оперативного диспетчерского управления процессом.
Genesis32 предоставляет возможности использования паке-
та для мобильных применений с помощью средств Pocket Genesis
для карманных компьютеров и MobileHMI для мобильного те-
лефона.
SCADA-система iFIX (Intellution, США)
iFIX входит в состав интегрированного пакета FIX Dynamics
(ПО Intellution Dynamics). FIX Dynamics — полностью инте-
грированное решение на основе стандарта ОРС, COM/DCOM-
технологии, VBA. Ядром пакета является система I-CORE, пред-
назначенная для объединения всех приложений. Компонентами
I-CORE являются подсистемы тревог (alarms), защиты (security),
конфигурирования (SCU), поддержки сети (Network), ОРС-клиент,
VBA и Workspace. Вокруг ядра I-CORE располагаются другие
подсистемы, в том числе база данных реального времени, кото-
рая взаимодействует с остальными приложениями по протоколу
ОРС.
Спецификации протокола разработаны компаниями, входящи-
ми в общество ОРС Foundation (140 компаний — членов общества).
Основная цель спецификации — стандарт на разработку драйверов
между контроллерами и SCADA-системами.
Скорость обмена данными определяется тем, что он проводит-
ся через общую память и реализуется модулями динамической би-
блиотеки DLL или локальным ЕХЕ-сервером.
Пакет iFIX является 32-разрядным ПО, работающим с ОС
Windows, поддерживающим распределенную архитектуру кли-
ент-сервер. Пакет iFIX основан на современных технологиях ОРС,
COM, ActiveX, VBA и других.
Ядром пакета iFIX является БД реального времени, состоящая
из набора стандартных блоков-тэгов (более 30 типов), с помощью
которых менеджер БД предоставляет широкие возможности по
разработке и ведению БД. Имеется возможность экспорта-импорта
базы данных из текстовых файлов. БД может выступать как серве-
ром, так и клиентом.
18
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
Среда разработки и отображения проектов Intellution Workspace
предоставляет широкие графические возможности и позволяет
разрабатывать проект в единой среде с интуитивно понятным ин-
терфейсом. Intellution Workspace имеет встроенный язык програм-
мирования VBA.
Поддерживает два режима:
- Configuration (конфигурирование или разработка проекта);
- RunTime (режим выполнения).
Пакет iFIX поддерживает внедрение объектов ActiveX, что по-
зволяет помещать на мнемосхеме любые доступные компоненты.
В числе объектов ActiveX поставляется Сводка тревог для контроля
аварийных ситуаций на производстве в реальном масштабе време-
ни. В iFIX имеется инструмент VisionX для получения информации
из реляционных баз данных (SQL Server, Oracle, SyBase, Informix,
DB2 и других). С его помощью осуществляется связь с ODBC- или
OLE DB-источниками без программирования (знание языка SQL
не требуется). VisionX представляет собой набор готовых объектов
ActiveX, которые интегрируются в Intellution Workspace. Для защи-
ты системы от сбоев, вызванных некорректной работой объектов,
используется технология Secure Containment. Intellution Workspace
имеет большие возможности анимации объектов, значения параме-
тров которых могут определяться математическими выражениями,
поступающими с различных SCADA-серверов.
Для ускорения разработки проекта имеются библиотеки гото-
вых объектов Dynamo, которые содержат законченные элементы
изображения со встроенными скриптами на VBA. Эти библиотеки
могут быть дополнены объектами, созданными пользователем с по-
мощью Мастера объектов или заимствованными у других произво-
дителей. Графические изображения мнемосхем могут иметь расши-
рения различных форматов: bmp, jpg, wmf и другие. В iFIX имеется
возможность резервирования серверов и сетей.
Пакет iFIX поддерживает клиент-серверную архитектуру, когда
имеются SCADA-серверы и узлы-клиенты (iClient). SCADA-сервер
выполняет сбор данных, их анализ, архивацию, генерацию тревог
и организацию диспетчерского управления. Узел iClient получает
данные от SCADA-серверов и реализует функции визуализации
и диспетчерского управления.
19
РАЗРАБОТКА SCADA-СИСТЕМ
Существует ряд решений для организации управления техно-
логическим процессом через Internet. К их числу относится пакет
iClientTS для Terminal Server и iWebServer, служащий для удален-
ного доступа и просмотра производственного процесса через Internet.
Пакет iClientTS — это стандартный клиент iFIX, работающий
на платформе Windows Terminal Server. В качестве терминалов могут
выступать любые компьютеры и терминалы ввода-вывода. Работа
клиента в терминальном режиме осуществляется через Web-браузер.
Клиент iClientTS может разрабатывать и просматривать экранные
формы, используя VBA-скрипты, тренды, алармы. Пакет предостав-
ляет возможность удаленной работы с iFIX с любого компьютера
в сети без необходимости устанавливать iFIX на клиентских ком-
пьютерах.
iWebServer — средство удаленного доступа для просмотра
производственного процесса через Internet в реальном масштабе
времени с помощью стандартного Web-браузера: Internet Explorer,
Netscape Navigator и другие. С помощью Web-браузера имеется воз-
можность просматривать тревоги и архивы.
iBatch — программный пакет для контроля и управления пе-
риодическими процессами в химической, фармацевтической, пи-
щевой и других отраслях промышленности. Одной из функций
пакета iBatch является Active Journaling — ведение журнала собы-
тий с получением информации в реальном масштабе времени.
Другая функция пакета — Active Binding, предназначена для ди-
намической перенастройки оборудования, подключения установок
и выведения их из процесса. Для интеграции с ERP и MES систе-
мами в iBatch предусмотрены функции VBIS. Пакет iBatch под-
держивает язык программирования SFC, технологии COM/DCOM,
ActiveX.
infoAgent — Web-клиент для представления и анализа истори-
ческих данных iHistorian. Экранные формы infoAgent обеспечивают
удобное представление данных, построение графиков, трендов по
времени и по событиям.
iVisualize — программный продукт для создания интерфейса
операторских панелей на базе ОС Windows СЕ. IVisualize вклю-
чает в себя среду разработки Intellution Workspace для создания
и настройки экрана операторской панели и модуль исполнения
20
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
под Windows СЕ. iVisualize является ОРС-сервером и поддерживает
основные промышленные интерфейсы, в том числе Date Highway+,
Profibus, DeviceNet, Modbus, Ethernet и другие.
iDownTime — ПО, позволяющее обнаружить и сократить вре-
мя простоя оборудования и тем самым повысить эффективность
работы предприятия. Анализ работы предприятия и составление
отчета о простоях, причинах и местах возникновения простоя про-
изводятся на основе архива iFIX.
iHistorian — исторический архив масштаба предприятия, обе-
спечивающий сбор, хранение и предоставление производственной
информации пользователям. iHistorian — гибкая масштабируемая
система, способная создавать как небольшие локальные архивы
до 1 000 параметров, так и архивы до 100 000 параметров (тегов)
на одном сервере. Производительность сервера составляет до
20 000 событий в секунду. Хранение значений параметров и данных
осуществляется в файловой системе, а не в реляционной базе дан-
ных. iHistorian поддерживает многосерверную структуру, т. е. архив
с распределенной базой данных и возможностью добавления новых
серверов. Каждый клиент имеет возможность получения данных
с нескольких серверов и представления их на одном экране.
Программный пакет OneStep Configuration Suite — это па-
кет для соединения ПЛК компании Schneider Electric и HMI. Пакет
ПО позволяет сократить время, трудозатраты и стоимость при раз-
работке, отладке, документировании и тестировании ПО. OneStep
Configuration Suite включает три приложения — OneStep Link,
OneStep SCD (Smart Control Devices) и OneStep Generator.
OneStep Link — совместная разработка фирм Intellution и
Schneider Electric, которая автоматически связывает базу данных
iFIX HMI и базу данных ПЛК, создаваемую в программной среде
Concept.
OneStep SCD — набор многократно используемых объектов,
связывающий графические элементы с функциональными блоками
ПО Concept. В результате снижается время на разработку проекта.
OneStep Generator автоматически конфигурирует память ПЛК
и устройств ввода-вывода, используя библиотеку функциональных
блоков. Он осуществляет сигнализацию, архивирование и диагно-
стику.
21
РАЗРАБОТКА SCADA-СИСТЕМ
SCADA-система Trace Mode (AdAstra Research Group, Россия)
Trace Mode — это 32-разрядная SCADA-система, имеющая
сертификат Госстандарта РФ и широко распространенная в России
и странах СНГ. Trace Mode является интегрированной SCADA/HMI
и SoftLogic системой, когда разработка приложений для оператор-
ских станций и контроллеров производится в рамках одного проекта
на базе единого ПО. За счет использования принципов автопострое-
ния проекта сокращаются время его разработки и стоимость.
Архитектура системы Trace Mode — это клиент-серверная ар-
хитектура с использованием общей модели объектов DCOM для ОС
Windows. Основу Trace Mode составляет мощный сервер и БД ре-
ального времени. Связь с клиентскими модулями, приложениями
SCADA-систем, У СО и СУБД осуществляется через стандартные
интерфейсы DCOM, ОРС, HTTP, DDE, Т-СОМ, ActiveX, SQL/ODBC.
Основные функции системы Trace Mode 5:
- модульная структура с числом каналов от 128 до 64000x16;
- встроенная поддержка российских контроллеров «Реми-
конт», «Ломиконт», Ш711, КРУИЗ, МФК, ЭК2000 и других;
- поддержка международного стандарта на средства програм-
мирования контроллеров IEC 61131-3;
- библиотека драйверов контроллеров фирм Rockwell
Automation, Siemens, Schneider Electric, Moeller, PEP, Fisher
Rosemount и других;
- средства программирования PC-base контроллеров MIC2000,
ROBO, Lagoon, TREI;
- встроенная система более 150 алгоритмов АСУ ТП, в том
числе алгоритмы фильтрации, ПИ- и ПИД-регулирования,
нечеткое и позиционное регулирование, ШИМ-преобразо-
вание и другие, а также адаптивная настройка регуляторов;
- открытость для встраивания пользовательских алгоритмов
и форм отображения ActiveX;
- возможность резервирования локальных сетей, датчиков, ар-
хивов с автоматическим восстановлением после сбоя.
Суть автопостроения, ускоряющего разработку проекта, за-
ключается в автоматическом генерировании баз каналов оператор-
ских станций и контроллеров на основе информации о числе точек
22
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
ввода-вывода, номенклатуре контроллеров и У СО, характере связи
между ПК и ПЛК.
Благодаря автопостроению разработка АСУ ТП сводится к сле-
дующему:
1. В рабочем поле редактора базы каналов размещаются пик-
тограммы (объекты) контроллеров и операторских станций.
2. Указываются число сигналов ввода-вывода и наличие ин-
формационного обмена между узлами.
3. Запускается автопостроение, которое автоматически фор-
мирует базы каналов проекта.
Разработка графического интерфейса осуществляется с помо-
щью Редактора представления данных (аналогичного Редактору
базы каналов), который позволяет создавать мнемосхемы техноло-
гических объектов и динамические объекты: гистограммы, тренды,
бегущие дорожки и т. д. Библиотека объектов включает емкости,
теплообменники, кнопки и другие объекты. Пользователь может
на языке Visual Basic (VB) создать собственные формы как ActiveX
и встроить их в Trace Mode. Возможна отладка проекта из редактора
Trace Mode в режиме реального времени.
По протоколам TCP/IP, IPX/SPX, DCOM, DDE/NetDDE, ОРС
осуществляется связь с офисными приложениями Excel, Access, MS
SQL Server, Oracle, SyBase, BaseStar, R/3, программами «Парус»
и «Галактика» на уровне АСУП.
Основу ПО диспетчерского уровня управления составляют
монитор реального времени (МРВ). МРВ Trace Mode — это сервер
реального времени, осуществляющий прием данных с контролле-
ров, управление процессом, визуализацию информации, ведение
архивов (с дискретностью 0,001 с.).
Trace Mode содержит средства для разработки АРМ руководи-
теля с помощью модулей Supervisor, которые предоставляют руко-
водителю всю необходимую информацию о параметрах и состоя-
нии технологического процесса.
Trace Mode позволяет создавать резервированные многоуров-
невые АСУ ТП масштаба предприятия на базе ведущих сетевых ОС
с обменом по протоколам NetBios, NetBEUI, IPX/SPX, TCP/IP. Се-
тевые комплексы допускают структурирование с выделением сле-
дующих уровней:
23
РАЗРАБОТКА SCADA-СИСТЕМ
- контроллеров;
- диспетчерского уровня;
- административного уровня.
Оформление отчетов о ходе технологического процесса осу-
ществляется с помощью сервера документирования. Сервер при-
нимает данные от удаленных модулей и обрабатывает их в соот-
ветствии со сценариями. Готовые отчеты могут быть записаны
в файл, выведены на печать, экспортированы в СУБД или пред-
ставлены в Internet. Для обмена информацией по сети Internet ис-
пользуется Web-сервер Trace Mode. Технология клиента позво-
ляет осуществлять визуализацию процесса, формировать тренды
и алармы, формировать управляющие воздействия с помощью
Web-браузера.
Trace Mode поддерживает технологии телеуправления через
GSM и SMS. GSM-активатор для Windows предоставляет пользова-
телям на сотовые телефоны отчеты тревог, позволяет передавать с
сотового телефона команды управления, получать информацию по
запросу с сотового телефона.
SCADA-система SIMATIC WinCC (Siemens, Германия)
Основу WinCC составляет базовая система, поддерживающая
основные интерфейсы SCADA-систем: ОРС, ActiveX, ODBC, SQL
и другие.
В состав базовой системы входят следующие компонен-
ты: Control Center, Graphics Designer, Alarm Logging, Tag Logging,
User Archiv, Report Designer, Global Scripts, User Administration.
Control Center выполняет следующие функции:
- обзор данных проекта и глобальных установок системы;
- запуск среды разработки или исполнения; формирование об-
щей базы данных переменных и сообщений с контроллеров
Simatic; осуществление коммуникаций с контроллерами;
- конфигурацию многопользовательской клиент-серверной
сетевой системы.
Graphics Designer используется для создания мнемосхем и ди-
намических графических элементов с использованием:
- стандартных объектов (текстов, линий, прямоугольников,
кругов, статической графики и т. д.);
24
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
- пользовательских объектов управления, ActiveX объектов;
- режима On-line, поддержки OLE Automation.
Alarm Logging применяется для сбора и архивации событий
в системе. Поступающие сообщения отображаются, а также могут
генерировать звуковые сигналы тревоги. Сообщения могут под-
тверждаться оператором (квитироваться) в зависимости от степени
важности.
Tag Logging используется для архивирования измеряемых ве-
личин. Архивация производится по выбору в базу данных Sybase
Anywhere, или в формат DBASE. Данные из архива отображаются
в виде кривых или таблиц. Возможно формирование данных для
статистической оценки работы системы, а также импорт и экспорт
архивов на внешний носитель.
User Archive служит для хранения пользовательских данных
в форме записей со свободно-параметрируемой структурой, опре-
деляемой пользователем. Доступ к базам данных осуществляется
через ODBC, SQL, WinCC API.
Report Designer служит для генерации отчетов в свободно про-
граммируемом формате, управляемых событиями или по времени.
Генерируются протоколы поступающих сообщений, измеряемых
величин и архивов, протоколы пользовательских отчетов, распечат-
ки списков переменных и т. д.
Global Scripts служит для программирования действий, про-
изводимых с объектами, а также программ, выполняющихся в фо-
новом режиме. Функции, разработанные пользователем на языке
ANSI-С, могут считывать и устанавливать значения переменных,
вызывать на экран новые изображения, генерировать сообщения об
ошибках, генерировать протоколы, подключать динамические би-
блиотеки.
User Administration служит для удобного управления правами
доступа пользователей в системе.
Ко всем перечисленным модулям WinCC имеет API интерфейс.
Система поддерживается ОС Windows (системная шина PCI).
MasterSCADA (ИнСАТ, Россия)
Пакет MasterSCADA рекомендуется использовать на компью-
терах с ОС Windows.
25
РАЗРАБОТКА SCADA-СИСТЕМ
В структуру пакета заложены основные принципы: единая сре-
да разработки, раздельное конфигурирование структуры АСУ ТП
и логической структуры объектов, объектный подход и открытость
интерфейсов.
MasterSCADA имеет единую среду разработки, т. е. обеспечи-
вается единство программирования SCADA/HMI и контроллеров
(SoftLogic).
Все функции системы разработки сосредоточены в един-
ственном окне. Имеются дерево объектов, отображающее техно-
логическую иерархию объектов, и дерево системы, отображающее
техническую структуру системы. Все объекты имеют свойства, до-
кументы (окна, тренды) и позволяют производить действия с до-
кументами и переменными. Методом перетаскивания в документ
может быть встроен рисунок.
Для создания графических изображений имеется обширная
библиотека технологических элементов, объемные трубопроводы,
встроенный инструмент создания мультипликации.
Пакет имеет более 150 функций и функциональных блоков для
проектирования систем управления, допускает формульные вычис-
ления значений параметров и событий, создание текущих и архив-
ных трендов и их экспорт во внешние базы данных. Также имеется
гибкая система создания алармов, автоматическое формирование
сообщений и другие функции.
Система поддерживает стандарт ОРС, технологию ActiveX,
допускает встраивание любых внешних программ в оболочку
MasterSCADA, экспорт проекта и всех документов в формат HTML,
экспорт архивов и журналов в БД, создание отчетов в MS Excel.
MasterSCADA имеет учебник, содержащий порядок и примеры раз-
работки проекта.
SCADA-система VNS (ИнСАТ, Россия)
Пакет программ VNS (VTC Next Step) предназначен для раз-
работки операторских станций в распределенных системах управ-
ления. VNS поддерживает работу с контроллерами «Ломиконт»,
«Ремиконт-130», ТСМ51, MFC, Ш-711, Autolog, MicroPC, DEP
и другими.
26
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
Пакет VNS выполняет следующие функции:
- отображение графических мнемосхем с широкими возмож-
ностями динамизации;
- элементов и создания библиотек символов;
- оперативное управление процессом с помощью команд с кла-
виатуры, мыши, трекбола или сенсорного экрана, включая
контроль действий оператора и защиту от несанкциониро-
ванного доступа;
- вывод на экран и регистрацию текстовых сообщений;
- отображение исторических трендов длительностью до года;
- печать отчетов по времени, событию и по вызову;
- обмен данными и файлами по сети, создание архива на сервере;
- свыше 100 алгоритмов обработки переменных;
- возможность расширения пакета собственными алгоритма-
ми, программами, драйверами и библиотеками символов.
Технические характеристики пакета VNS:
- минимальный период опроса — 0,2 с.;
- число элементов мнемосхемы — 1 200;
- число мнемосхем — не ограничено;
- число узлов сети — 255;
- число контроллеров на узел сети — 250;
- число параметров на узел сети — 4 000;
- число отчетов, сообщений — 4 000.
SCADA-система КРУГ-2000, (КРУГ, Россия)
КРУГ-2000 является открытой SCADA-системой с поддержкой
международных стандартов Fast Ethernet, CAN, DeviceNet, Modbus,
RS232, RS-485, UDP, TCP/IP, COM, DCOM, OPC.
Пакет имеет единую, целостную базу данных системы, сете-
вую загрузку ПО контроллеров, поддержку стандарта IEC 61131-3.
Модульное построение среды разработки и среды исполнения
(Run-time) серверов, станций и контроллеров позволяет оптимизи-
ровать выбор аппаратных средств и снизить стоимость техническо-
го обеспечения системы.
В состав среды разработки входят:
- генератор базы данных,
- генератор динамики,
27
РАЗРАБОТКА SCADA-СИСТЕМ
- среда разработки программ пользователя на технологиче-
ском языке КРУГОЛ-61131 (на базе языков FBD и ST).
В состав среды исполнения входят:
- сервер БД, сервер ввода-вывода,
- сервер архива,
- сервер печати,
- двухмониторный менеджер.
Поддерживается ОС QNX, Linux, DOS.
SCADA-пакет имеет объектно-ориентированный графический
редактор, библиотеку стандартных графических символов и слож-
ных графических объектов, возможности анимации объектов, печати
и архивации отчетов. Создание статических мнемосхем осуществ-
ляется с помощью графического редактора ГРЕК, динамически из-
меняющихся элементов мнемосхем с помощью редактора ДИНАР.
Работа с трендами: возможность масштабирования трендов,
одновременный вывод исторических трендов и трендов РВ, дискре-
тизация до 100 мс.
Возможна организация алармов по скорости изменения сигна-
ла и по отклонению. Имеется возможность задания 9 уровней при-
оритетов.
Пакет предусматривает возможность его связи с контроллера-
ми TREI-05 и другими контроллерами, а также с системами верхне-
го уровня по сетям Novell, Ethernet.
SCADA-система Genie З.о (Advantech, Тайвань)
Пакет Genie 3.0 является инструментальной средой для созда-
ния ПО систем сбора данных и оперативного диспетчерского управ-
ления (SCADА), исполняемого в среде Windows. Применяется для
проектирования небольших АСУ ТП масштаба участка или цеха.
Genie имеет модульно-ориентированную, открытую интегрирован-
ную архитектуру. Открытость архитектуры позволяет легко реали-
зовать взаимодействие Genie с другими приложениями для совмест-
ного доступа к данным в реальном масштабе времени.
Управление всеми данными Genie в реальном масштабе вре-
мени, а также хранение и обработку данных осуществляет Центр
обработки данных (Date Center). Пакет состоит из двух основных
программных модулей:
28
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
- построителья стратегии GENIE (GENIE.EXE),
- исполнительной среды GENIE (GWRUN.EXE).
Построитель стратегии используется для проектирования и те-
стирования проектов (стратегий), а исполнительная среда — только
для исполнения стратегий.
Стратегия — это совокупность одной или нескольких задач
вместе с одной или большим числом экранных форм, а также одним
сценарием.
Простейшая стратегия имеет одну задачу с одной экранной
формой и не имеет основного сценария.
Задача, экранная форма и основной сценарий являются тремя
основными элементами проектирования стратегий.
Экранная форма представляет собой набор элементов отобра-
жения и элементов управления. Элементы отображения — это гра-
фик, текстовая строка, индикатор и т. д. К элементам управления
относятся кнопка, аналоговый, движковый или инкрементный ре-
гулятор.
Пиктограммы блоков и элементы являются стандартными
блоками для построения стратегии. Соединения между функцио-
нальными блоками могут устанавливаться посредством видимых в
окне редактора задач связей, называемых проводником. Соединение
между пиктограммой блока и элементом отображения или между
двумя элементами отображения невидимы, и поэтому они называ-
ются связями.
Построитель стратегий GENIE предоставляет пользователю
для проектирования АСУ ТП четыре различных редактора:
- редактор задач (Task Designer);
- редактор форм отображения (Display Designer);
- редактор отчетов (Report Designer);
- редактор сценариев (Script Designer).
Они используются для редактирования задач, экранных форм
отображения, отчетов и основных сценариев соответственно.
Редактор задач (Task Designer) предназначен для реализации
прикладных алгоритмов создаваемой системы. Разработка системы
сводится к размещению пользователем функциональных блоков в
окне задачи и установлению между ними связей, определяемых ал-
горитмом обработки данных. Genie 3.0 обеспечивает возможность
29
РАЗРАБОТКА SCADA-СИСТЕМ
разработки и одновременного исполнения до 8 задач. Более сложная
задача может быть разбита на несколько простых задач меньшего
объема, что упрощает процесс разработки и увеличивает произво-
дительность при исполнении, поскольку при каждом сканировании
должно быть обработано меньшее число функциональных блоков.
Редактор форм отображения (Display Designer) предназна-
чен для создания динамических графических форм отображения,
связанных с исполняемой стратегией сбора данных и управления.
При необходимости создания графического интерфейса оператора
возможно использование специальных инструментов рисования
и элементов отображения, таких как насосы, клапаны, круги, прямо-
угольники, сегменты и т. д. Кроме того, пользователь может конфи-
гурировать цвета и размеры указанных графических примитивов.
Genie предоставляет команды «Сгруппировать» и «Разгруппиро-
вать», позволяющие объединять графические примитивы в единое
изображение.
Редактор отчетов (Report Designer) предназначен для разработ-
ки и генерации отчетов. Пользователь может разрабатывать формат
отчета с использованием специального инструмента табличной
формы и определять расписание для автоматической печати отче-
та. К другим функциям Редактора отчетов относятся: сбор данных,
конфигурирование формата отчетов, генерация отчетов событий,
генерация отчетов тревог.
Редактор сценариев (Script Designer) предназначен для управ-
ления задачами, вычислениями и анализом данных в реальном
масштабе времени. Genie предоставляет средства разработки про-
граммных сценариев, совместимые с VBA. Поскольку VBA явля-
ется одним из самых популярных и простых для изучения языков
программирования, его наличие в пакете позволяет значительно
упростить и повысить эффективность разработки проекта с исполь-
зованием Genie.
Центр обработки данных (Date Center) является набором библи-
отек динамической компоновки (DLL-библиотек) и предназначен
для хранения и обработки данных, связанных с работой стратегии
под управлением исполнительной среды Genie. Центр обработки
данных поддерживает три способа взаимодействия пакета Genie
с другими Windows-приложениями:
30
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
- интерфейс прикладного программирования (С API);
- механизм динамического обмена данными (DDE);
- механизм связывания и внедрения объектов (OLE
Automation).
Для взаимодействия Genie с аппаратными средствами в ре-
альном масштабе времени используются драйверы ввода-вывода
(I/O Drivers). Драйверы ввода-вывода поддерживают все аппарат-
ные средства промышленной автоматизации фирмы Advantech,
включая:
- модули сбора данных и управления ADAM и другие,
- PC-совместимый модульный контроллер MIC-2000,
- устройства удаленного сбора данных и управления серий
ADAM-4000 и ADAM-5000/485,
- устройства ADAM-5000/CAN промышленной шины CAN
с протоколом DeviceNet.
1.2. ОРС-стандарт обмена информацией SCADA-систем
иПЛК
Стандарт ОРС (OLE for Process Control) — это стандарт
взаимодействия между программными компонентами системы
сбора данных и управления, основанный на объектной модели
COM/DCOM фирмы Microsoft.
Стандарт ОРС приходит на смену DDE-обмена (Dynamic Date
Exchange — динамический обмен данными).
COM (Component Object Model) — модель многокомпонент-
ных объектов, позволяющая приложению вызывать те или иные
функции объекта, находящегося в адресном пространстве прило-
жения. Если объект распределен по сети или находится в другой
программе того же компьютера, то мы имеем распределенный
COM (Distributed СОМ) или DCOM. Таким образом, DCOM являет-
ся, по сути, сетевым расширением СОМ.
ОРС-технология создана консорциумом ОРС Foundation, куда
входят более 170 ведущих производителей аппаратно-программ-
ных средств промышленной автоматизации. Среди этих фирм —
Siemens, Fisher-Rosemount, Honeywell, Rockwell, Iconics и другие.
Деятельность ОРС Foundation осуществляется в рабочих груп-
пах по направлениям ОРС Date Access Working Group, ОРС Alarm
31
РАЗРАБОТКА SCADA-СИСТЕМ
and Events Working Group, OPC Historical Working Group, OPC
Security Working Group, OPC Windows CE Working Group.
ОРС-взаимодействие основано на клиент-серверной архи-
тектуре. В качестве ОРС-клиента выступает, например, SCADA,
а в качестве ОРС-сервера — контроллеры, УСО. Основные про-
изводители SCADA-систем поддерживают технологию ОРС. Это
SCADA-системы Genesis32 (фирма Iconics), FIX Dynamics (фирма
Intellution), InTouch (фирма Wonderware) и другие. При этом все
компоненты SCADA-систем могут взаимодействовать между собой
через ОРС, выполняя функции в зависимости от задачи либо серве-
ра, либо клиента.
ОРС-серверы разрабатываются и поставляются производителя-
ми контроллеров и другой аппаратуры или поставщиками SCADA-
систем. Стандарт ОРС включает 3 основных спецификации:
- доступ к данным реального времени (Data Access) или стан-
дарт DA;
- обработка тревог и событий (Alarm & Events, или стандарт
А&Е);
- доступ к историческим данным (Historical Data Access) или
стандарт HDA.
ОРС-серверы физических устройств (контроллеров) являются,
как правило, серверами данных (Data Access Servers).
Сервер тревог по состоянию тега, полученного от сервера дан-
ных, оповещает клиентов, посылая сигнал тревоги, и получает от
клиентов подтверждение полученного сигнала.
Серверы исторических данных также используют данные, по-
лучаемые в реальном времени от сервера данных, и архивируют их,
предоставляя затем эти данные другими приложениям для построе-
ния трендов, гистограмм или таблиц.
Кроме этих основных спецификаций стандарта ОРС существу-
ет и ряд других спецификаций. Так, отдельный класс ОРС-серверов
представляют специализированные ОРС-серверы конкретных ап-
паратных устройств.
Рассмотрим работу ОРС-сервера в клиент-серверной архитек-
туре.
При использовании COM/DCOM технологии реализуется
информационный обмен между COM-объектами. Вызов любой
32
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
функции объекта осуществляется через COM-интерфейс, представ-
ляющий определенную структуру памяти, содержащую массив ука-
зателей на все функции интерфейса. Этот вызов реализуется через
агента-посредника, так называемого Proxy/Stab DLL, представляю-
щего функции объекта. Модуль Proxy (заместитель) принадлежит
клиенту, а модуль Stab (заглушка) расположен в сервере.
Proxy реагирует на запрос клиента, кодируя и пакетируя пара-
метры функции, после чего передает их по каналу серверу. На сто-
роне сервера модуль Stab распаковывает вызов клиента и передает
его серверу, заставляя реальный объект выполнить заданную функ-
цию. Результат выполнения функции возвращается обратно прило-
жению-клиенту.
Этот процесс получил название маршалинг (англ, marshaling —
транспортировка). На рис. 1.1 представлена последовательность дей-
ствий при клиент-серверной передаче данных (цифрами показана
временная последовательность передачи данных).
Основной спецификацией ОРС является спецификация Data
Access (DA). Базовым понятием спецификации является элемент
данных OPCItem-объект, т. е. фактически один из параметров тех-
нологического процесса, имеющий значение Data Value, время по-
следнего обновления Time Stamp и признак качества (достоверно-
сти) значения Quality.
при клиент-серверной передаче данных
(цифрами показана временная последовательность передачи данных)
33
РАЗРАБОТКА SCADA-СИСТЕМ
Следующим вверх по иерархии является понятие группы эле-
ментов OPCGroup-объект. Группа создается ОРС-сервером по тре-
бованию клиента, который задает частоту обновления данных этой
группы. Для каждого клиента сервером создается своя группа. Эле-
менты в группе имеют имена, являющиеся, по сути, именами реаль-
ных переменных (тегов). Имена тегов клиентом запрашиваются по
специальному интерфейсу lOPCBrowseServerAdressSpace.
На верхней ступени иерархии находится сам OPC-Server-
объект. Для подключения ОРС-сервера к реальному объекту OPCItem-
объекты содержат ссылки на созданные ОРС-сервером теги. Пример
полного имени тега: Контроллер !. Модулъ_2. Аналоговый вход_1.
Обмен данными между клиентом и ОРС-сервером может про-
изводиться в трех режимах:
- синхронный режим чтения/записи данных;
- асинхронный режим чтения/записи данных;
- режим подписки (только чтение данных).
При синхронном режиме ОРС-клиент запрашивает у ОРС-сер-
вера интересующие его переменные и находится в режиме ожида-
ния. После выполнения запроса ОРС-клиент считывает значения
переменных.
При асинхронном режиме обмена ОРС-клиент запрашивает
у ОРС-сервера значения переменных с заданной частотой обновле-
ния данных, определенной при создании OPCGroup, и продолжает
работать. После выполнения запроса ОРС-сервер сам оповещает
об этом ОРС-клиента. Этот режим является наиболее распростра-
ненным в силу экономии вычислительных ресурсов и времени.
Режим подписки аналогичен асинхронному режиму с той лишь
разницей, что ОРС-сервер посылает ОРС-клиенту уведомление
лишь в случае изменения значений переменных. Передача этих дан-
ных осуществляется единым блоком с целью снижения временных
затрат, что особенно важно при обмене по сети.
Одной из основных характеристик ОРС-сервера является его
производительность. Известны три вида ОРС-серверов в зависимо-
сти от их местонахождения.
Внутризадачный ОРС-сервер (InProcess Server), находящийся
в адресном пространстве ОРС-клиента, оформлен как динамиче-
ская библиотека DLL, а не как самостоятельная программа.
34
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
Локальный ОРС-сервер (Local Server) — сервер работает в от-
дельной самостоятельной программе того же компьютера, в кото-
ром расположен ОРС-клиент.
Удаленный ОРС-сервер (Remote Server) — сервер расположен
на другом (удаленном по сети) компьютере.
Производительность внутризадачного сервера выше локально-
го, а последнего — выше, чем удаленного. Однако другим важным
фактором, влияющим на производительность ОРС-сервера, является
возможность группировки данных, отправляемых ОРС-клиентам.
Структура ОРС-сервера с открытой архитектурой представле-
на на рис. 1.2.
Открытая архитектура ОРС-сервера предусматривает возмож-
ность его работы (после небольшой доработки) с любым аппарат-
ным или программным средством, поддерживающим технологию
ОРС. Чтение данных с устройств ввода или прямо из кэш-памяти
данных осуществляется с помощью функции Read.
В свою очередь, функция ReadFromDevices опрашивает устрой-
ство ввода и передает данные ОРС-клиенту. Функция Write слу-
жит для записи данных ОРС-клиента на устройство вывода и/или
в кэш-память данных. Функции обновления устройства ввода,
кэш-памяти данных и ОРС-клиентов осуществляются с частотой,
заданной клиентом при формировании OPCGroup.
Рис. 1.2. Структура ОРС-сервера с открытой архитектурой
Таким образом, разработчик АСУ ТП при выборе SCADA-
системы, контроллеров и другой аппаратуры, поддерживающих
35
РАЗРАБОТКА SCADA-СИСТЕМ
технологию ОРС, может рассчитывать на взаимопонимание ком-
понентов системы. К сожалению, при наличии в системе аппарат-
ных средств других фирм, интерфейсы которых не поддерживают
ОРС-взаимодействие, использование их в сетевом обмене данными
затруднено. В этом случае требуется разработка специализирован-
ных ОРС-серверов, обладающих свойствами открытости. При этом
разработчик (пользователь) должен написать динамическую библи-
отеку DLL, содержащую полный код, необходимый для управления
конкретным устройством, либо обеспечить связь с соответствую-
щей DLL, поставляемой производителем этого устройства.
Специализированный ОРС-сервер разрабатывается на осно-
ве программной заготовки, созданной некоторыми фирмами. Так,
фирма Iconics, изначально спроектировавшая SCADA-систему
Genesis32 на основе ОРС-технологии, предлагает ОРС ToolWorX,
оформленный в виде дополнительного мастера в Wizard, который
встроен в среду разработки Visual C++.
Мастер генерирует проект, в котором требуется выполнить мо-
дификацию фрагментов кода, связанных со спецификой обслужи-
ваемого устройства нижнего уровня. Так, на базе Iconics ToolWorX
создан универсальный ОРС-сервер фирмы Fastwel — Universal ОРС
Server.
Этот ОРС-сервер предусматривает подключение динамиче-
ской библиотеки (DLL), написанной пользователем для конкрет-
ного устройства. Недостатком ОРС-сервера служит то, что клиент
получает данные из внутреннего буфера DLL, а не непосредственно
от устройства ввода, что служит причиной некоторой временной
задержки обмена данными. Для разработки ОРС-сервера в АСУ
ТП, использующей SCADA-систему FIX Dynamics, целесообраз-
но использовать пакет для разработки ОРС-приложений фирмы
Intellution.
1.3. Функции, выполняемые SCADA-системами
АСУ ТП в большинстве случаев являются системами органи-
зационно-техническими, что означает наличие функций, выполняе-
мых человеком-оператором.
Несколько десятков лет назад эти функции заключались в ос-
новном в наблюдении за контрольно-измерительными приборами
36
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
и непосредственном ручном управлении технологическим про-
цессом.
После того как компьютеризация достигла производственного
сектора, на рабочих столах операторов стали появляться компью-
теры, где взаимодействие между оператором и технологическим
процессом осуществляется с помощью программного обеспечения,
получившего общее название SCADA.
У отечественных специалистов и менеджеров предприятий,
занимающихся автоматизацией промышленности, нет однознач-
ного ответа на вопрос: нужно ли применять специализированное
программное обеспечение класса SCADA? Следует отметить, что
даже у тех, кто применяет такое программное обеспечение в своих
проектах, нет единого мнения по поводу того, как должна выглядеть
и каким требованиям должна отвечать идеальная SCADA-система.
Однозначного ответа на данные вопросы не существует, так же, как
не существует единственно правильного подхода к проектированию
систем промышленной автоматизации.
Важно различать программное обеспечение SCADA, функ-
ционирующее в составе АСУ ТП конкретного объекта, и набор
инструментальных программных средств, предназначенный для
разработки такого программного обеспечения. В этой связи и кри-
терии оценки средств разработки SCADA-систем и их пригодности
для реализации той или иной прикладной задачи должны лежать
в плоскости, несколько отличной от требований к прикладному про-
граммному обеспечению верхнего уровня АСУ ТП.
Обе разновидности ПО весьма тесно связаны (например,
runtime-компоненты инструментальной системы непосредственно
используются в объектовом ПО), поэтому мы будем называть их си-
стемами SCADA, надеясь на то, что читатель поймет из контекста,
о чем идет речь в каждом конкретном случае.
Остановимся на основных функциях, которые возлагаются
на любую SCADA-систему, независимо от того, является она ши-
роко тиражируемым продуктом известной компании или создана
специалистами отдела АСУ ТП предприятия для своих конкретных
нужд.
Рассмотрим понятие SCADA-система. В названии присут-
ствуют две основные функции, возлагаемые на SCADA-систему:
37
РАЗРАБОТКА SCADA-СИСТЕМ
- сбор данных о контролируемом технологическом процессе;
- управление технологическим процессом, реализуемое от-
ветственными лицами на основе собранных данных и пра-
вил (критериев), выполнение которых обеспечивает наи-
большую эффективность и безопасность технологического
процесса.
Согласно традиционной структуре аппаратных средств АСУ
ТП, показанной на рис. 1.3, SCADA-системы в иерархии программ-
ного обеспечения систем промышленной автоматизации находятся
на уровнях 2 и 3 и обеспечивают выполнение следующих основных
функций.
Уровень О: Датчики и н<пвяниг*г*.мые тчиюми
Рис. 1.3. Традиционная структура аппаратных средств АСУТП
1. Прием информации о контролируемых технологических па-
раметрах от контроллеров нижних уровней и датчиков.
2. Сохранение принятой информации в архивах.
3. Вторичная обработка принятой информации.
4. Графическое представление хода технологического процес-
са, а также принятой и архивной информации в удобной для
восприятия форме.
38
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
5. Прием команд оператора и передача их в адрес контролле-
ров нижних уровней и исполнительных механизмов.
6. Регистрация событий, связанных с контролируемым тех-
нологическим процессом и действиями персонала, ответ-
ственного за эксплуатацию и обслуживание системы.
7. Оповещение эксплуатационного и обслуживающего пер-
сонала об обнаруженных аварийных событиях, связанных
с контролируемым технологическим процессом и функцио-
нированием программно-аппаратных средств АСУ ТП с ре-
гистрацией действий персонала в аварийных ситуациях.
8. Формирование сводок и других отчетных документов на ос-
нове архивной информации.
9. Обмен информацией с автоматизированной системой управ-
ления предприятием или, как ее принято называть сейчас,
комплексной информационной системой.
10. Непосредственное автоматическое управление технологи-
ческим процессом в соответствии с заданными алгорит-
мами.
Можно коротко сказать, что SCADA-система собирает инфор-
мацию о технологическом процессе, обеспечивает интерфейс с опе-
ратором, сохраняет историю процесса и осуществляет автоматиче-
ское управление процессом в том объеме, в котором это необходимо.
Наличие некоторых функций и объем их реализации сильно ва-
рьируются от системы к системе. Часто программное обеспечение
с ярко выраженным упором на функции взаимодействия с операто-
ром (визуализация и т. д.) называют пакетами MMI (Man-machine
interface), или HMI (Human-machine interface).
На такой функции, как автоматическое управление, стоит
задержать наше внимание. Хотя практически все известные ин-
струментальные SCADA-системы обеспечивают возможность не-
посредственного автоматического управления технологическим
процессом, разработчику АСУ ТП следует на этапе проектирова-
ния тщательно продумать целесообразность совмещения функций
автоматического управления и операторского интерфейса на од-
ном компьютере. Хотя такое совмещение позволяет экономить на
аппаратных средствах, оно может иметь и ряд негативных послед-
ствий.
39
РАЗРАБОТКА SCADA-СИСТЕМ
Например, может оказаться, что операционная система опера-
торской станции (в настоящее время наиболее популярна Windows)
не обеспечивает необходимую для конкретного технологического
процесса скорость и/или детерминированность реакции SCADA-
системы.
Неумелые действия оператора или запуск им несанкциониро-
ванного программного обеспечения может вызвать полный «крах»
и «зависание» операторской станции. Хотя некоторые расширения
реального времени для Windows декларируют защиту от подобного
рода неприятностей, это справедливо только до тех пор, пока «кра-
хом» не задета система управления памятью. Но даже при «мягком
зависании» повторный «горячий» рестарт компьютера весьма про-
блематичен.
Существует довольно большой класс инерционных систем
(типа системы управления температурой воздуха в теплице), где
несколько минут, потраченных на перезапуск управляющего ком-
пьютера, не приводят к сколько-нибудь заметным негативным по-
следствиям. Для такого рода систем решение типа «все в одном ком-
пьютере» при надлежащей страховке сторожевым таймером может
оказаться вполне допустимым.
Перечисленные ранее функции могут выполняться приклад-
ной программой (набором прикладных программ), разработанной
на практически любом языке высокого уровня общего назначения.
По быстродействию, ресурсоемкости и другим показателям эффек-
тивности программного обеспечения такая программа может даже
опережать аналогичное ПО, созданное с помощью специализиро-
ванных инструментальных SCADA-систем.
При решении вопроса о том, писать программное обеспече-
ние самостоятельно или использовать для этого инструментальную
SCADA-систему, следует предварительно ответить на следующие
вопросы:
1. Насколько велик проект?
2. Каковы сроки исполнения?
3. Сколько человек будет задействовано в создании программ-
ной части, какова квалификация разработчиков программ-
ного обеспечения и имеют ли они наработки в данной об-
ласти?
40
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
4. Какова перспектива дальнейшего развития системы (в част-
ности, по информационной емкости, по модернизации
имеющихся рабочих мест оператора и добавлению новых)?
5. Каково количество и квалификация персонала, который бу-
дет обслуживать систему в процессе эксплуатации, в том
числе вносить изменения в алгоритмы ее работы?
Ответы на эти вопросы и оценка затрат по пунктам 3, 4, 5
в большинстве случаев позволяют сказать, на каких языках подготав-
ливать ПО для верхнего уровня АСУ ТП. Хотелось бы подчеркнуть,
что SCADA-системы являются прежде всего инструментом для эф-
фективной разработки программного обеспечения верхнего уровня
АСУ ТП. Так что не следует верить поставщикам SCADA-пакетов,
которые утверждают, что после покупки их продукта пользователю
совершенно не придется привлекать квалифицированных специа-
листов в области программирования.
В то же время в большинстве случаев SCADA-системы дей-
ствительно позволяют значительно ускорить процесс создания ПО
верхнего уровня АСУ ТП, не требуя при этом от разработчика зна-
ний современных процедурных языков программирования общего
назначения. Не секрет, что в тонкостях автоматизируемого техноло-
гического процесса разбирается только технолог или другой пред-
ставитель технологического персонала, как правило, не обладаю-
щий навыками программирования. SCADA-система должна быть
доступной не только для разработчика, но и для конечного пользо-
вателя создаваемой АСУ ТП, поскольку облик системы определяет-
ся и может подвергаться изменениям, как со стороны разработчика,
так и со стороны пользователя.
Помимо доступности, SCADA-системе должна быть присуща
максимальная открытость. Очень часто SCADA-системы имеют
весьма специфические механизмы обмена данными с аппаратурой
ввода-вывода. Более того, ряд SCADA-систем имеет встроенную
поддержку устройств ввода-вывода, что, с одной стороны, ограни-
чивает разработчика/пользователя в выборе технических средств,
на базе которых строится система. С другой стороны, это весьма
затрудняет реализацию поддержки как имеющихся на объекте кон-
троллеров и устройств связи с объектом, так и вновь появляющихся
серий и моделей контроллеров и устройств.
41
РАЗРАБОТКА SCADA-СИСТЕМ
Очень часто поддержка аппаратуры встроена в SCADA-
систему. При этом производители SCADA-системы, которым при-
ходится самостоятельно писать драйверы для различных типов
аппаратуры, очень редко могут качественно разработать драйвер,
который бы поддерживал все функциональные возможности обслу-
живаемых технических средств.
Кроме того, в подобных драйверах в силу отсутствия воз-
можности углубленного тестирования встречаются ошибки, кото-
рые выявляются на этапе разработки проекта или, что еще хуже,
в процессе эксплуатации системы заказчиком. В результате огром-
ные усилия тратятся на исправление ошибок и разработку новых
драйверов, тогда как по-настоящему эффективный и практически
свободный от ошибок драйвер может быть написан только самим
производителем аппаратуры.
Очевидно, что производитель SCADA-пакета должен в первую
очередь своевременно устранять ошибки и улучшать функциональ-
ность самого SCADA-пакета.
Важны умеренная цена и эффективное использование вложен-
ных средств, то есть стоимость системы, затраты на освоение и сто-
имость работ по созданию, сопровождению и развитию АСУ ТП
должны быть минимальными. При прочих равных условиях данное
требование является наиболее существенным и, пожалуй, решаю-
щим при выборе SCADA-системы.
Разработчики SCADA-систем всегда стараются извлечь мак-
симальную выгоду из продаж своего продукта (что вполне понят-
но), строя свой бизнес на продажах систем исполнения (runtime)
и множества различных функционально завершенных компонен-
тов, платном обучении, платных обновлениях и платном сопро-
вождении. При этом задача менеджера фирмы системного интегра-
тора или группы АСУ ТП предприятия, отвечающего за выбор спо-
соба и инструментов разработки программного обеспечения, состо-
ит в оценке предположительных временных и финансовых затрат
на разработку, сопровождение и последующее развитие созда-
ваемой АСУ ТП при использовании различных инструментов раз-
работки.
В приведенных ранее рассуждениях отсутствуют какие-либо
упоминания об операционных системах, под управлением которых
42
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
может выполняться программное обеспечение сбора данных и опе-
ративного диспетчерского управления. Уже несколько лет в различ-
ных изданиях, посвященных автоматизации промышленности, об-
суждение тех или иных SCADA-систем сводится к рассуждениям
о том, насколько плоха операционная система DOS, ненадежна
Windows, хороша QNX или OS9.
Нужно отметить, что требования к параметрам операцион-
ной системы должны определяться прикладной задачей. В слу-
чае программного обеспечения верхнего уровня АСУ ТП также
следует учитывать то, что неотъемлемой частью системы здесь
является человек, время реакции которого на события недетерми-
нировано и зачастую достаточно велико. Кроме того, нельзя не учи-
тывать тенденции развития мирового рынка программного обеспе-
чения.
1.4. Структура стандарта ОРС
ОРС — это стандарт взаимодействия между программными
компонентами системы сбора данных и управления (SCADА), осно-
ванный на объектной модели COM/DCOM фирмы Microsoft. Через
интерфейсы ОРС одни приложения могут читать или записывать
данные в другие приложения, обмениваться событиями, оповещать
друг друга о нештатных ситуациях (тревогах), осуществлять доступ
к данным, зарегистрированным в архивах («исторические» данные).
Эти приложения могут располагаться как на одном компьютере, так
и быть распределенными по сети.
При этом независимо от фирмы поставщика стандарт OLE
for Process Control, признанный и поддерживаемый всеми веду-
щими фирмами — производителями SCADA-систем и оборудова-
ния, обеспечит их совместное функционирование. Особый класс
ОРС-приложений представляют собой ОРС-серверы конкретных
аппаратных устройств — они поставляются многими произво-
дителями аппаратуры, а также независимыми производителями,
но в этом случае они, как правило, небесплатные.
ОРС-сервер создает своего рода абстракцию аппаратуры, по-
зволяя любому ОРС-клиенту записывать и считывать данные с
устройства. Устройство, для которого есть ОРС-сервер, может ис-
пользоваться вместе с любой современной SCADA-системой.
43
РАЗРАБОТКА SCADA-СИСТЕМ
Теперь у пользователя — системного интегратора или разра-
ботчика АСУ ТП — появилась возможность выбирать оптимальные
для своей системы компоненты, а не ориентироваться, как раньше,
целиком на «монолитные» решения, предлагаемые тем или иным
поставщиком.
ОРС может использоваться только там, где установлен
Microsoft DCOM (Windows и теоретически некоторые системы се-
мейства Unix).
В целом ОРС — это интерфейс для системы верхнего уровня.
Ниже лежащие слои — PLC, У СО и т. д. — представлены для нее
в виде ОРС-серверов и в общем случае являются «черными ящи-
ками».
Далее, ОРС не обеспечивает работы в жестком реальном вре-
мени, поскольку в DCOM отсутствуют понятия качества обслужи-
вания, крайних сроков и т. и. В то же время контроль за «старением»
данных имеется: каждое передаваемое значение (тег) сопровож-
дается меткой времени происхождения (timestamp). Несмотря на то,
что требования жесткого реального времени, строго говоря, не вы-
полняются, реальная частота передачи данных порядка 50 миллисе-
кунд достигается без каких-либо специальных мер.
Не следует думать, что любое устройство можно просто так
«через ОРС» подключить к любой SCADA-системе, — для этого
надо иметь ОРС-сервер. Сервер можно либо получить вместе с
устройством, либо купить, либо написать самостоятельно. Послед-
нее не так уж сложно и, как правило, является наилучшим рецеп-
том при модернизации уже сложившихся систем управления, где
используется нестандартная аппаратура. Так можно получить впол-
не «современное» лицо системы (используя, например, SCADA-
систему Genesis32 фирмы Iconics), сохранив при этом проверенный
аппаратный и даже программный задел. Разработанные ранее ал-
горитмы управления можно просто встроить в разрабатываемый
ОРС-сервер.
Как отмечалось ранее, реализация ОРС основана на объект-
ной модели COM/DCOM фирмы Microsoft. COM (Component Object
Model — модель многокомпонентных объектов) позволяет прило-
жению манипулировать удаленными программными объектами,
точнее, вызывать те или иные функции (методы) этих объектов так,
44
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
как будто объекты находятся «рядом». Объект может находиться
и в самом деле рядом (в адресном пространстве приложения). Тогда
это просто СОМ.
Если же объект находится в другой программе на том же ком-
пьютере или на другом узле сети, то это DCOM (Distributed) —
распределенная СОМ. В распределенном случае (DCOM) вызов
любой функции объекта перехватывается специальным агентом-
посредником, так называемой proxy/stub DLL, которая выполняет
роль представителя объекта у обратившегося к нему клиента.
Proxy/stub DLL упаковывает параметры функции (marshaling —
транспортировка) и передает вызов операционной системе, кото-
рая (возможно, по сети) доставляет вызов по назначению, то есть
заставляет реальный объект выполнить заданную функцию. Ре-
зультат затем возвращается (примерно по той же цепочке) прило-
жению-клиенту. Удобство использования DCOM состоит в том, что
приложение-клиент совершенно не обязано знать, где реально на-
ходится объект — о степени удаленности объекта оно может судить
только по увеличению расхода времени на вызов функции.
ОРС-взаимодействие основано на клиент-серверной схеме.
ОРС-клиент, например, SCADA-система, вызывая определен-
ные функции объекта ОРС-сервера, подписывается на получение
определенных данных с определенной частотой. В свою очередь
ОРС-сервер, опросив физическое устройство, вызывает известные
функции клиента, уведомляя его о получении данных и вручая сами
данные. Таким образом, при ОРС-взаимодействии используются
как прямые COM-вызовы (от клиента к серверу), так и обратные
(callback, от сервера к клиенту). Это надо учитывать при настрой-
ках безопасности DCOM в Windows: если клиент «видит» данные,
но не получает их, значит, скорее всего, система безопасности
Windows блокировала обратные вызовы.
Стандарт ОРС, в отличие, например, от устаревшего DDE
(Dynamic Data Exchange), хотя и основан на универсальном фун-
даменте — COM/DCOM, разрабатывался специально для исполь-
зования в промышленной автоматизации, поэтому он имеет вполне
содержательную концептуальную сторону. Он имеет свою проблем-
но-ориентированную модель взаимодействия, которая и реализо-
вана через совокупность COM-интерфейсов. Эта концептуальная
45
РАЗРАБОТКА SCADA-СИСТЕМ
сторона в известной степени независима и представляет самый
большой интерес, особенно для пользователя — не программиста,
для которого тонкости реализации COM-интерфейсов не столь важ-
ны. В принципе, основные идеи ОРС могли бы быть реализованы
и с помощью других объектных технологий, однако распространен-
ность Windows-платформ предопределила выбор в пользу стандар-
тов Microsoft.
Стандарт ОРС состоит из трех основных спецификаций:
- доступ к данным реального времени (Data Access);
- обработка тревог и событий (Alarms & Events);
- доступ к историческим данным (Historical Data Access).
В соответствии с этим ОРС-серверов тоже может быть три
вида, хотя не возбраняется совмещать все эти функции в одном.
ОРС-серверы физических устройств обычно являются только сер-
верами данных (Data Access Servers).
Серверы тревог и исторические чаще всего основываются
на серверах данных.
Сервер тревог формирует определенные логические перемен-
ные, называемые состояниями (conditions), имея в качестве исход-
ной информации некую переменную (тег), полученную от сервера
данных. Состояния изменяют свое значение, если переменная, на-
пример, вышла за допустимые границы. Об изменении состояния
сервер тревог оповещает клиентов, посылая им событие (тревогу),
а клиент возвращает серверу подтверждение, что он тревогу вос-
принял. Впрочем, могут существовать состояния, не связанные с
каким-либо параметром и управляемые сервером тревог по соб-
ственному усмотрению (например, если сервер тревог напрямую
взаимодействует с аппаратурой, он может устанавливать или сни-
мать состояние неисправности).
Серверы исторических данных получают от серверов данных
параметры в реальном времени и архивируют их, а затем предостав-
ляют эти данные другим приложениям (например, для построения
графиков трендов).
Центральное место среди спецификаций ОРС занимает доступ
к данным реального времени (Data Access). Это самая старая и от-
работанная спецификация, в настоящее время действует ее вторая
версия.
46
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
Базовым понятием этой спецификации является элемент дан-
ных (Item). Каждый элемент данных (то есть фактически — пара-
метр технологического процесса) имеет:
- значение,
- время последнего обновления (timestamp),
- признак качества, определяющий степень достоверности
значения.
Значение может быть:
1. Скалярного типа:
- булевого,
- целого,
- с плавающей точкой.
2. Строкового типа, точнее OLE VARIANT.
Время представляется со 100-наносекундной точностью
(FILETIME Win32 API).
Качество — это код, содержащий в себе грубую оценку досто-
верности параметра — UNCERTAIN, GOOD и BAD («не опреде-
лено», «хорошее» и «плохое»), а на случай плохой оценки — еще
и расшифровку, например, QUALSENSORFAILURE — «неисправ-
ность датчика».
Следующим вверх по иерархии является понятие группы эле-
ментов ОРС Group.
Группа создается ОРС-сервером по требованию клиента, ко-
торый затем может добавить в группу элементы (Items). Для груп-
пы клиентом задается частота обновления данных, и все данные
в группе сервер старается обновлять и передавать клиенту с задан-
ной частотой. Отдельно стоящих вне группы элементов быть не
может. Клиент может создать для себя на сервере несколько групп,
различающихся требуемой частотой обновления. Группа (кроме
так называемых публичных групп) всегда создается для каждого
клиента своя, даже если состав элементов и частоты обновления со-
впадают. Отсоединение клиента приводит к уничтожению создан-
ных для него групп.
Элементы в группе — это своего рода клиентские ссылки на
некие реальные переменные (теги), находящиеся на сервере или в
физическом устройстве. Понятие тега спецификацией ОРС не опре-
деляется, но подразумевается неявно. Элементы в группу клиент
47
РАЗРАБОТКА SCADA-СИСТЕМ
добавляет по имени. Эти имена, разумеется, на самом деле яв-
ляются именами соответствующих тегов. Клиент может либо знать
нужные имена заранее, либо запросить список имен тегов у сервера.
Для запроса имен тегов служит интерфейс lOPCBrowse
ServerAddressSpace, с помощью которого сервер описывает клиен-
ту свое «пространство имен», организованное в общем случае ие-
рархически. Пример полного имени тега: Устройство 1. Модуль 2.
Аналоговый Вход 3 (в качестве разделителя используется точка). При
добавлении элемента в группу клиент всегда указывает это полное
имя. Заметим, что группы, создаваемые клиентом на сервере, не обя-
заны совпадать (и, как правило, не совпадают) с подразделами про-
странства имен сервера, элементы в группу добавляются вразнобой.
Единственное, что их объединяет, — это общая частота обновления
и синхронность отправки клиенту.
Наконец, на верхней ступеньке иерархии понятий находит-
ся сам ОРС-сервер. Из всех перечисленных (ОРС-группа, ОРС-
элемент) он единственный является COM-объектом, все остальные
объекты доступны через его интерфейсы, которые он предоставляет
клиенту.
Обмен данными между клиентом и сервером может осущест-
вляться в двух режимах — синхронном и асинхронном. При асин-
хронном варианте обмена сервер сам оповещает клиента об изме-
нившихся значениях данных, на которые подписался клиент (по
возможности с частотой, заданной клиентом при создании груп-
пы). При синхронном режиме клиент осуществляет инициатив-
ное чтение или запись данных. Запись может быть только синх-
ронной.
Затраты ресурсов компьютера на поддержку ОРС-взаимодей-
ствия и предельно достижимая интенсивность обмена между кли-
ентом и сервером зависят от ряда факторов, но прежде всего от того,
находится ли сервер непосредственно в адресном пространстве
клиента (т. е. внутризадачный — In Process Server) или он является
самостоятельным приложением.
В последнем случае важно, расположен сервер на том же ком-
пьютере, что и клиент, или на другой станции локальной сети. Тре-
тий по важности фактор — это возможность группировки данных
для отправки клиентам. Так, передача раз в 1 секунду 100 тегов
48
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
займет значительно меньше ресурсов, чем одного тега через каждые
10 миллисекунд.
Стандарт ОРС разрабатывает независимая организация —
ОРС Foundation, насчитывающая более 170 членов, среди которых
Siemens, Fisher-Rosemount, Honeywell, Rockwell, Iconics и дру-
гие, то есть практически все известные компании производители
SCADA-систем и оборудования для систем промышленной автома-
тизации.
Утвержденные спецификации ОРС, а также proxy/stub DLL,
соответствующая интерфейсам ОРС, свободно доступны с Web-
узла ОРС Foundation. Строго говоря, этого достаточно для разра-
ботки своего ОРС-сервера. Однако разработка сервера «с нуля» —
довольно сложный процесс, а аккуратная реализация интерфейсов
ОРС в многопоточной (multithread) среде изобилует различными
«подводными камнями». Это представляет известную опасность,
так как ОРС-сервер обязан быть достаточно надежной програм-
мой.
Проще всего разработать сервер, используя специально соз-
данные для этого средства. Так, фирма Iconics, известная своей
SCADA-системой Genesis, предлагает ОРС ToolWorX, который
оформлен в виде дополнительного мастера (Wizard), встраиваемого
в среду разработки Visual C++.
Мастер генерирует исходный проект, в котором требуется
только модификация фрагментов кода, связанных со спецификой
обслуживаемого устройства или протокола. Поддержка ОРС взаи-
модействия обеспечивается специальными классами объектов, не
требующими каких-либо исправлений, поэтому программист может
сосредоточиться на функциональности своего устройства, не забо-
тясь о реализации собственно ОРС-интерфейсов. Все компоненты
ОРС ToolWorx поставляются в исходном коде. Для квалифициро-
ванного программиста срок разработки несложного ОРС-сервера
с помощью Iconics ОРС ToolWorX — 3-4 недели.
В случае если к серверу не предъявляются особо жесткие требо-
вания к синхронности обновления данных и не требуется динамиче-
ская реструктуризация пространства имен во время его работы, мож-
но применить самое простое и недорогое решение — универсальный
ОРС-сервер фирмы Fastwel. Он создан на базе IconicsToolWorX
49
РАЗРАБОТКА SCADA-СИСТЕМ
и предусматривает подключение динамической библиотеки (DLL),
написанной пользователем, в которой сосредоточен весь код, специ-
фичный для обслуживаемого устройства.
Интерфейс этой DLL с сервером очень прост, и разработка ее
для простых устройств (или когда уже есть соответствующий про-
граммный задел в виде ранее написанных драйверов и т. и.) зани-
мает у квалифицированного программиста всего 1-3 дня. Вместе
с универсальным ОРС-сервером (в виде исполняемого модуля) по-
ставляется исходный текст «образцовой» DLL, который можно ис-
пользовать как пример реализации.
Практически все производители SCADA-систем поддержи-
вают OLE for Process Control, среди них — Fix Dynamics (Intellution),
FactorySuite 2000 (Wonderware), Genesis32 (Iconics), FactoryLink
(US Data), Lookout (National Instruments) и т. д. Однако для боль-
шинства из них ОРС — только один из поддерживаемых интерфей-
сов взаимодействия.
Их внутренняя идеология построения напрямую не связана с
этим стандартом и часто унаследована от предыдущих 16-разрядных
версий. По-видимому, пока только Genesis-32 изначально спроекти-
рован на основе ОРС (ОРС to the Core). Все компоненты Genesis-32
взаимодействуют между собой через ОРС, являясь, в зависимости от
ситуации, либо серверами, либо клиентами, либо и теми и другими
одновременно. Это придало системе во многом единый стиль, строй-
ность архитектуры и предопределило ее компонентный характер:
унификация интерфейсов взаимодействия дала возможность легко
выбирать совокупность компонентов, действительно необходимых
пользователю, и не переплачивать за ненужные. Конечно, у других
SCADA-систем есть свои сильные стороны, однако Genesis32 в наи-
большей степени дает своим пользователям почувствовать свободу
выбора, которую обеспечивает ОРС.
База данных тегов — единое хранилище всех переменных,
используемых в проекте. Теги могут быть системными (например,
время и дата), разделяемыми с другими приложениями и пользова-
тельскими. Возможные типы: двоичные, целые, с плавающей точ-
кой и строковые. Возможно определение массивов тегов, классов
тегов и указателей на теги.
50
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
1.5. Структура компьютерной распределенной системы
управления и организация программного обеспечения
диспетчерского уровня
Современные РСУ представляют собой сложные компьютер-
ные системы (рис. 1.4), реализованные на основе:
- промышленных сетей, объединяющих контроллеры;
- сетей, объединяющих удаленные компьютеры/удаленные
рабочие станции (УК/УРС).
Будем в дальнейшем такие системы называть компьютерными
распределенными системами управления (КРСУ).
Контроллерный уровень КРСУ
Контроллеры образуют нижний уровень КРСУ. Этот уро-
вень называется контроллерным. К контроллерам подключается
технологическое оборудование. Программы, управляющие этим
оборудованием, находятся в памяти контроллеров. Эти програм-
мы разрабатываются, как правило, на языках программирования
ПЛК по стандарту IEC 61131-3. К таким языкам, например, отно-
сится язык FBD (Functional Block Diagrams) — язык функциональ-
ных блоковых диаграмм, входящий в систему программирования
контроллеров UltraLogik. UltraLogik имеет средства по загрузке
подготовленной управляющей программы в любой контроллер
сети.
На этом уровне решается задача непосредственного управ-
ления технологическим оборудованием в реальном времени. Одна-
ко контроллеры выполняют еще одну важную функцию: они отправ-
ляют определенную информацию о ходе технологического процес-
са или текущем состоянии технологического оборудования в про-
мышленную сеть, которая их объединяет. Эта информация пред-
ставлена в виде тегов. Каждый тег несет информацию о величи-
не определенной переменной управляющей программы. С этой пе-
ременной связано значение того или иного технологического па-
раметра. Важно, чтобы переменная, значение которой необходимо
передавать в сеть, имела статус «сетевая».
51
РАЗРАБОТКА SCADA-СИСТЕМ
Диспетчерский уровень КРСУ
На верхнем диспетчерском уровне КРСУ расположены ком-
пьютеры и рабочие станции, предназначенные для решения за-
дач визуализации информации, полученной из контроллеров, ее
архивирования, ведения журналов тревог и т. д. Таким образом,
на рабочих станциях этого уровня должны быть установлены
SCADA-системы.
Среди УК/УРС диспетчерского уровня выделяется один, ко-
торый выполняет роль мастера промышленной сети. Он имеет
программное обеспечение, позволяющее ему обмениваться ин-
формацией как с контроллерами нижнего уровня, так и с УК/УРС
диспетчерского уровня.
По сети Ethernet информация о технологическом процессе мо-
жет передаваться от мастера на другие УК/УРС верхнего уровня.
Другими словами, мастер содержит программное обеспе-
чение, позволяющее считывать значения тегов из промышлен-
ной сети PLCNet и передавать их на другие рабочие станции сети
Ethernet.
Программное обеспечение компьютеров
диспетчерского уровня
Более детальное изображение КРСУ с одним мастером пока-
зано на рис. 1.5. В нижней части этого рисунка показаны аппарат-
ные средства двух сегментов промышленной сети PLCNet. Дис-
петчерский уровень представлен N удаленными компьютерами
(slave).
52
ПМ1
Рис. 1.4. Современные РСУ
Рис. 1.5. КРСУ с одним мастером
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
Программное обеспечение этих компьютеров реализовано в
виде SCADA-систем, которые в программном смысле являются
ОРС-клиентами ОРС-сервера, расположенного на мастере. На масте-
ре расположен ОРС-сервер Fastwel PlcNet ОРС Server фирмы Fastwel.
Именно он читает теги из промышленной сети PLCNet и обе-
спечивает их временное хранение. ОРС-клиенты, расположенные
на УК/УРС сети Ethernet, могут прочитать значения этих тегов.
Но для этого на мастере должны быть расположены и запущены два
приложения:
- объект автоматизации (Automation object), проектирование
которого рассмотрено в разделе 3.2;
- утилита scktsrvr.exe, которая поставляется совместно со
средой программирования Delphi (ее необходимо располо-
жить в списке автозагрузки мастера).
На мастере может работать свой ОРС-клиент. Он на рис. 1.5
не показан. Он может получать информацию непосредственно
с ОРС-сервера, не используя объект автоматизации.
Примеры конкретной реализации КРСУ
На рис. 1.6 приведена структура КРСУ, содержащая два кон-
троллера ADAM-5510 и N рабочих станций диспетчерского уровня.
Одна из них используется в качестве мастера.
На рис. 1.6 в качестве сменяемого оборудования, подключае-
мого к контроллерам, используются два макета. Опишем их более
подробно, поскольку именно они будут использоваться для имита-
ции работы технологического оборудования. Информация с датчи-
ков этих макетов будет визуализироваться просмотрщиками тегов,
рассмотренных в разделах 2.2 — 2.6.
Макет 1 (расположен справа на рис. 1.6) содержит:
- 16 датчиков дискретного типа (кнопочные переключатели)
с выходными сигналами 0 или 1;
- 8 аналоговых датчиков (потенциометров) с выходными сиг-
налами 0...+5 В.
Этот макет был использован для отладки просмотрщиков те-
гов, рассмотренных в разделах 2.2 — 2.5.
Макет 2 (расположен слева на рис. 1.6) представляет собой ма-
кет ворот, которые могут перемещаться в горизонтальной плоскости
55
РАЗРАБОТКА SCADA-СИСТЕМ
влево или вправо. Величина перемещения контролируется датчи-
ком перемещения. Датчик перемещения представляет собой потен-
циометр, вал которого связан с исполнительным механизмом ворот
(электромотором). Выходной сигнал датчика находится в диапазоне
0...+5 В. Этот макет был использован для отладки просмотрщика
тегов, который будет рассмотрен в разделе 2.6.
На рис. 1.7 показана структура ПО рабочей станции — масте-
ра и остальных (удаленных) рабочих станций, образующих верхний
уровень РСУ.
Рабочая станция — мастер содержит:
- клиент 1 (ОРС Client) — приложение, разработанное в Delphi
и выполняющее функции SCADA-системы;
- ОРС-сервер фирмы Fastwel (Fastwel PLCNet ОРС Server);
- объект автоматизации (Automation Object) — приложение,
разработанное в Delphi и предназначенное для организации
обмена информацией между ОРС-клиентами удаленных ра-
бочих станций КРСУ и ОРС-сервером, расположенном на
рабочей станции — мастере.
Преобразователь интерфейсов
Рис. 1.6. Структура КРСУ
56
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
Удаленные рабочие станции содержат только ОРС-клиент-при-
ложение, выполняющее функции SCADA-системы.
Для того чтобы SCADA-система нормально работала, обя-
зательно необходимо, чтобы контроллеры были включены, рабо-
тали по программе, а нужные переменные имели бы статус «се-
тевая».
Преобразователь
интерфейсов
ADAM-4520
Клиент N
(ОРС
Client)
Рабочая станция N
Рабочая станция 1 (мастер)
10-20 метров
Сервер
Автоматизации
(Automation
Object)
Fastwel
PLCNet
ОРС Server
Клиент 1
(ОРС Client)
Рис. 1.7. Структура ПО рабочих станций, образующих верхний уровень РСУ
1.6. Fastwel PIcNet ОРС Server —ОРС-сервер
для сетей PLCNET
Общие сведения
Программа является сервером ОРС для узлов сети ULTRANET,
созданных с помощью системы программирования UltraLogik и
объединенных через интерфейс RS-485 (PLCNET) либо через стан-
дартную сеть Ethernet с помощью протокола IPX/SPX (IPXNET).
Сервер позволяет осуществлять обмен данными между узлами се-
тей PLCNET и IPXNET и приложениями-клиентами ОРС. Сервер
57
РАЗРАБОТКА SCADA-СИСТЕМ
реализован с использованием современных концепций программи-
рования на основе спецификации ОРС версии 2.0
Функциональные возможности программы
1. Поддержка признака достоверности сигналов, передаваемо-
го клиентам ОРС.
2. Поддержка до 4 независимых сегментов сети PLCNet
(RS-485) одновременно.
3. Поддержка до 2 независимых сегментов сети IPXNet
(IPX/SPX) одновременно.
4. Автоматическая генерация тегов для узлов сети.
5. Поддержка ОРС Data Access Automation Interface.
6. Поддержка интерфейса просмотра пространства имен
lOPCBrowseServerAddressSpace.
7. Поддержка генерации события _ServerShutDown в случае
принудительного завершения сервера.
Требования к системному программному обеспечению
Для корректного функционирования программы ПК должен со-
держать перечисленное ниже системное программное обеспечение.
1. Операционная система Windows с DCOM.
2. Для работы с сетями IPXNET в операционной системе
должна быть установлена поддержка протокола, совмести-
мого с IPX/SPX.
Содержимое установочного диска
Программа поставляется на компакт-диске либо может быть
загружена с ftp-узла фирмы ProSoft (ftp://ftp.prosoft.ru/pub/Software/
орс/ PLCNetOPC/). В комплект поставки входят:
- сервер ОРС,
- упрощенный клиент ОРС (приложение ОРС Client),
- электронная версия руководства пользователя,
- электронная версия руководства по настройке DCOM для
связи между ОРС-клиентом и удаленным ОРС-сервером,
- библиотека динамической компоновки OPCDAAuto.dll,
реализующая стандартный интерфейс ОРС Automation 2.0,
58
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
- пример клиента ОРС на Visual Basic 6.0,
- текстовый файл readme.txt, который содержит полезную ин-
формацию.
Установка программы
1. Вставьте компакт-диск Fastwel Software Product CD в привод
CD-ROM. Нажмите кнопку «Пуск» (Start) в панели инструментов
Windows и выберите команду «Выполнить» (Run). В диалоговой па-
нели «Выполнить» (Run) введите следующую команду:
G:\Full\FastwelPlcNet ОРС Server\PLCNetOPCServer.exe.
Если приводу компакт-диска отведена другая буква дискового
накопителя, соответствующим образом измените команду запуска.
Если производится установка демонстрационной версии про-
граммы, используйте следующую команду запуска:
G:\Demo\Fastwel PlcNet ОРС Server\PLCNetOPCServer.exe.
2. Следуйте указаниям программы установки. Если устанавли-
вается полная версия программы, программа установки отобразит
запрос о вводе серийного номера. Серийный номер напечатан на бу-
мажном конверте компакт-диска Fastwel Software Product CD. Далее
программа установки предложит выбрать каталог, в котором будут
размещены основные файлы сервера.
Как указывалось выше, для работы программы требуется нали-
чие операционной системы Windows с установленными системны-
ми компонентами DCOM. При установке браузера Internet Explorer
установка DCOM выполняется автоматически.
Удаление программы
Удаление программы следует выполнять штатными средства-
ми операционной системы. Для удаления вызовите «Панель управ-
ления» и сделайте двойной щелчок левой клавишей мыши на пик-
тограмме «Установка/Удаление программ» (Add/Remove Programs).
В списке установленных программ выберите строку PLCNET ОРС
Server и нажмите кнопку «Добавить/Удалить...» (Add/Remove...).
Следуйте указаниям мастера установки/удаления программ.
59
РАЗРАБОТКА SCADA-СИСТЕМ
Обзор технологии ОРС
НазначениеОРС
Технология связывания и внедрения объектов для систем про-
мышленной автоматизации ОРС предназначена для обеспечения
универсального механизма обмена данными между датчиками, ис-
полнительными механизмами, контроллерами, устройствами связи
с объектом и системами представления технологической информа-
ции, оперативного диспетчерского управления, а также системами
управления базами данных. Производители аппаратных средств,
пользуясь спецификацией ОРС, имеют возможность разрабатывать
единый сервер ОРС для обеспечения единственного и наиболее об-
щего способа организации доступа к данным и передачи в адрес
приложений-клиентов различных производителей программного
обеспечения для промышленной автоматизации.
ОРС основана на модели распределенных компонентных объ-
ектов Microsoft DCOM и устанавливает требования к классам объ-
ектов доступа к данным и их специализированным (custom) интер-
фейсам для использования разработчиками клиентских и серверных
приложений. Для обмена данными с приложениями-клиентами,
разработка которых ведется на языках типа MS Visual Basic, а также
с популярными приложениями типа Excel, спецификация ОРС со-
держит дополнительные (но необязательные для реализации) тре-
бования к интерфейсу OLE-автоматизации (OLE Automation).
Структура взаимодействия между приложениями-клиентами
и серверами ОРС различных производителей показана на рис. 1.8.
Рис. 1.8. Структура взаимодействия между приложениями-клиентами
и серверами ОРС
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
Опираясь на объектную технологию COM/DCOM, стандарт
ОРС фиксирует определенную модель взаимодействия между
клиентом и сервером.
Базовым понятием этой модели является элемент данных
(Item). Каждый элемент данных имеет значение, время последнего
обновления (timestamp) и признак качества, определяющий степень
достоверности значения. Значение может быть практически любого
скалярного типа — булево, целое, с плавающей точкой и т. п. — или
строкой (OLE VARIANT).
Время представляется с 100-наносекундной точностью
(FILETIME Win32 API). Реальная точность измерения времени
обычно бывает хуже и в общем случае зависит от реализации сер-
вера и аппаратуры. Качество — это код, содержащий в себе грубую
оценку — UNCERTAIN, GOOD и BAD («не определено», «хоро-
шее» и «плохое»), а в случае оценки «плохое» еще и расшифровку,
например QUAL_SENSOR_ FAILURE — ошибка датчика.
Следующим вверх по иерархии является понятие группы эле-
ментов (ОРС Group). Группа создается ОРС-сервером по требова-
нию клиента, который затем может добавлять в группу элементы
(Items). Для группы клиентом задается частота обновления данных,
и все данные в группе сервер старается обновлять и передавать
клиенту с заданной частотой.
Отдельно стоящих вне группы элементов быть не может.
Клиент может создать для себя на сервере несколько групп,
различающихся требуемой частотой обновления. Для каждо-
го клиента всегда создается своя группа (кроме так называемых
публичных групп), даже если состав элементов и частоты обнов-
ления совпадают. Отсоединение клиента приводит к уничтожению
группы.
Элементы в группе, таким образом, — это своего рода клиент-
ские ссылки на некие реальные переменные — теги, находящиеся
на сервере или в физическом устройстве. Понятие тега специфика-
цией ОРС не определяется, но подразумевается неявно. Элементы
в группу клиент добавляет по имени, и эти имена являются именами
соответствующих тегов. Клиент может либо знать нужные имена
заранее, либо запросить список имен тегов у сервера. Для запро-
са имен тегов служит интерфейс lOPCBrowseServerAddressSpace,
61
РАЗРАБОТКА SCADA-СИСТЕМ
с помощью которого сервер описывает клиенту свое пространство
имен, организованное в общем случае иерархически.
Пример полного имени тега: Устройство 1. Модуль 5. Ана-
логовый вход 3. При добавлении элемента в группу клиент всег-
да указывает это полное имя. Заметим, что группы, создаваемые
клиентом, не обязаны совпадать (и, как правило, не совпадают) с
подразделами пространства имен сервера.
Элементы в группу добавляются вразнобой. Единственное, что
их объединяет — это общая частота обновления и синхронность от-
правки клиенту.
На верхней ступеньке иерархии понятий находится сам
ОРС-сервер. Из всех перечисленных (ОРС-группа, ОРС-элемент)
он единственный является COM-объектом. Все остальные объекты
доступны через его интерфейсы, которые он предоставляет клиенту.
Взаимосвязь групп и элементов ОРС показана на рис. 1.9.
Рис. 1.9. Взаимосвязь групп и элементов ОРС
62
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
Установление соединения между клиентом и сервером
на одном компьютере
Установочная программа автоматически производит регистра-
цию сервера (запись соответствующей информации в системный
реестр). Программы-клиенты, как правило, имеют соответствую-
щий пользовательский интерфейс, позволяющий выбрать из списка
зарегистрированных серверов нужный (при этом если сервер неак-
тивен, он автоматически запустится), пролистать его адресное про-
странство и подписаться на необходимые теги.
Таким образом, для обеспечения соединения на одной машине
каких-либо специальных настроек (кроме установки сервера и кли-
ентского программного обеспечения, например, SCADA-системы)
производить не нужно.
До установки сервера на компьютере с Windows сначала долж-
на быть установлена Microsoft DCOM. Если на компьютере уже
установлена SCADA Genesis32 фирмы Iconics, то DCOM заведомо
установлен.
В комплект поставки программы входит упрощенный клиент
ОРС, позволяющий проверить работоспособность PLCNET ОРС-
сервера.
Установление соединения между клиентом
и удаленным сервером
Для работы в сети (клиент и сервер на разных компьютерах)
необходимо присутствие в сети хотя бы одной станции с уста-
новленной Windows (Server или Workstation). Станция с Windows
используется в качестве сервера авторизации и аутентифика-
ции.
При этом сам ОРС-сервер может располагаться как на ней, так
и на другой сетевой станции. Таким образом, минимальная конфи-
гурация из двух машин:
- Windows с установленным ОРС-сервером,
- Windows с установленным ОРС-клиентом.
Перед установлением соединения между приложением-клиен-
том и удаленным сервером следует произвести настройку систем-
ных компонентов DCOM. Процедура настройки DCOM является
63
РАЗРАБОТКА SCADA-СИСТЕМ
общей для всех ОРС-серверов и описана в отдельном руководстве,
входящем в комплект поставки.
Работа с ОРС-сервером
Указания по работе с программой, приведенные ниже, во мно-
гом сходны для обеих поддерживаемых сетей ULTRANET. В том
случае, если какие-либо действия, выполняемые для настройки од-
ной из сетей, имеют существенные особенности, их описание пред-
варяется надписью: «Для сети PLCNET (RS-485)» или «Для сети
IPXNET (IPX)».
Шаг1
Для сети PLCNET (RS-485):
1. Смонтируйте сеть PLCNET.
2. Загрузите соответствующие проекты UltraLogik в контрол-
леры.
3. Соедините контроллеры согласно указаниям документации,
поставляемой с системой UltraLogik и используемой аппа-
ратурой.
4. Подключите сеть к персональному компьютеру. Это мож-
но сделать через стандартный последовательный порт с ис-
пользованием преобразователя типа Advantech ADAM-4520,
ICP DAS 1-7520 и т. и. либо через платы расширения, напри-
мер, Advantech PCL-743/745B и им подобные, имеющие ин-
терфейс RS-485 и распознаваемые операционными система-
ми как дополнительные СОМ-порты.
5. При необходимости можно подключить к компьютеру до-
полнительные сегменты PLCNET (максимум 4), каждый
новый сегмент через отдельный последовательный порт.
Для сети IPXNET (IPX):
1. Соедините контроллеры и персональный компьютер сетью
Ethernet.
2. Установите протокол IPX/SPX на персональном компьютере.
3. В операционной системе Windows нажмите кнопку Start
и выберите строку Network and Dial-up Connections в меню
Settings.
64
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
4. В появившемся окне щелкните правой клавишей мыши на
пиктограмме Local Area Connection и выберите команду
контекстного меню Properties.
5. В появившейся диалоговой панели Local Area Connection
Properties нажмите кнопку Install...
6. В появившейся диалоговой панели SelectNetwork Component
Туре выберите строку Protocol, после чего нажмите кнопку
Add.
7. В появившейся диалоговой панели Select Network Protocol
выберите строку NWLink IPX/SPX/NetBIOS Compatible
Transport Protocol и нажмите кнопку OK.
8. После успешного добавления протокола перезапустите
компьютер.
9. Создайте и загрузите соответствующие проекты UltraLogik
в контроллеры. Настройка протокола IPX в контроллерах
описана в руководстве по UltraLogik.
Шаг 2
Включите питание компьютера и контроллеров в сети.
ШагЗ
Запустите программу Fastwel PLCNet ОРС Server.
Шаг 4
Щелкните левой клавишей мыши на кнопке «Новый сег-
мент UltraNet»1 |СТ |. В появившейся диалоговой панели, показанной
на рис. 1.10, заполните свойства сегмента сети:
1. Введите имя создаваемого сегмента в поле «Имя». При не-
обходимости имя сегмента может быть впоследствии изме-
нено.
Для сети PLCNET (RS-485):
2. Выберите логический номер сегмента в выпадающем списке
«Номер (1-6)». Номер сегмента PLCNET может быть от 1
до 4. Логические номера должны быть разными для каждо-
го сегмента, соответствующего одному последовательному
порту. После выбора номера сегмента выпадающий список
«Номер (1-6)» становится недоступным для редактирования.
65
РАЗРАБОТКА SCADA-СИСТЕМ
Кроме этого, из диалоговой панели убирается кнопка «От-
мена».
3. В выпадающем списке «COM-порт» выберите имя после-
довательного порта, к которому подключен добавляемый
сегмент PLCNET.
4. В выпадающем списке «Скорость» выберите скорость обме-
на, которая используется в добавляемом сегменте PLCNET.
5. В группе параметров «Собственный адрес (16-чн)» устано-
вите диапазон адресов, в рамках которого ОРС-сервер выбе-
рет для себя рабочий адрес в сети PLCNET. В этот диапазон
не должны входить адреса других узлов сегмента PLCNET
и широковещательный адрес FF. Чем шире диапазон (при
соблюдении указанного ограничения), тем быстрее ОРС-
сервер установит соединение с узлами.
6. Если в данном сегменте PLCNET имеются два ОРС-серве-
ра, что не рекомендуется для сети PLCNET на базе низко-
скоростного и ресурсоемкого интерфейса RS-485, то диапа-
зоны адресов обоих серверов не должны пересекаться.
Рис. 1.10. Диалоговая панель программы Fastwel PLCNet ОРС Server,
сеть PLCNET (RS-485)
66
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
Для сети IPXNET:
2. Выберите логический номер сегмента в выпадающем спи-
ске «Номер (1-6)» (рис. 1.11). Номер сегмента IPX может
быть 5 или 6, логические номера должны быть разными для
каждого сегмента, соответствующего одному «сокету» IPX.
После выбора номера сегмента выпадающий список «Номер
(1-6)» становится недоступным для редактирования. Кроме
того, из диалоговой панели убирается кнопка Отмена.
Рис. 1.11. Диалоговая панель программы Fastwel PLCNet ОРС Server,
сеть IPXNET
3. Введите шестнадцатеричное четырехзначное значение
«сокета» IPX в поле IPX socket (hex). Это значение должно
соответствовать установленному для контроллеров, входя-
щих в добавляемый сегмент IPXNET. По умолчанию задано
значение 8000. Сервер поддерживает до двух «виртуаль-
ных» IPX-сетей контроллеров (сегменты 5 и 6), которые
различаются значением сокета.
4. В группе параметров «Собственный адрес (16-чн)» уста-
новите диапазон адресов, в рамках которого ОРС-сервер
67
РАЗРАБОТКА SCADA-СИСТЕМ
выберет для себя рабочий адрес в сети IPXNET. В этот ди-
апазон не должны входить адреса других узлов сегмента
IPXNET и адрес FF (широковещательный). Чем шире диа-
пазон (при соблюдении указанного ограничения), тем бы-
стрее ОРС-сервер установит соединение с узлами.
Шаг 5
Нажмите кнопку «Применить». Установленные значения па-
раметров сегмента будут восприняты ОРС-сервером, после чего
сервер произведет сканирование сегмента сети UltraNet. По за-
вершении сканирования в списке группы «Поиск узлов» появятся
шестнадцатиричные значения адресов найденных узлов.
Шаг 6
Введите в поле «Адрес (16-чн)» группы параметров «Узел»
значение адреса узла сети UltraNet, таблицу переменных которого
требуется считать, из числа найденных или выберите адрес в списке
«Поиск узлов» и нажмите кнопку « . Выбранный адрес появится
в поле «Адрес (16-чн)» группы параметров «Узел».
Шаг7
Нажмите кнопку «Создать». На время считывания конфигу-
рации узла курсор мыши примет вид песочных часов, а в группе
параметров «Связь» появятся значения, отражающие количество
пакетов, посланных узлу по сети без ошибок и с ошибками. Если
конфигурация не была полностью считана за время порядка 5 се-
кунд, на экране появится сообщение о целесообразности продолже-
ния попыток связи с узлом.
В случае если в группе параметров «Связь» не зафиксировано
попыток связи, завершившихся успешно, то рекомендуется прекра-
тить попытки чтения конфигурации узла и проверить физическое
соединение, состояние узла сети и правильность настроек.
Для протокола PLCNET следует проверить правильность адре-
са узла и соответствие установленного значения скорости обме-
на используемому в сети PLCNET. При использовании протокола
IPX следует убедиться в соответствии номера сокета, заданного в
поле IPX socket (hex), номеру, установленному для узлов сети IPX.
При совпадении номеров сокета следует установить флажок «Только
68
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
широковещательные адреса» и попытаться связаться с узлами
вновь. Если зафиксированы удачные попытки связи, то рекомен-
дуется продолжать операцию до ее завершения.
Шаг 8
После того, как узел успешно создан, в древовидной структу-
ре сети, отображаемой в левой части диалоговой панели, должен
появиться его адрес. Раскрытие созданного узла приведет к появ-
лению списка его сетевых переменных. Если в указанном списке
выбрать какую-либо переменную, в группе параметров «Перемен-
ная» диалоговой панели будет отображаться информация о пере-
менной, включая имя, тип, текущее значение (обновляемое с часто-
той 4 раза в секунду) и качество: good — «хорошее» или bad —
«плохое», в зависимости от результатов последней операции чте-
ния.
Шаг 9
Повторите процедуру создания узла для всех узлов данного
сегмента сети, доступ к переменным которых должен осущест-
вляться через Fastwel PLCNET ОРС-сервер.
Шаг 10
Нажмите кнопку ОК диалоговой панели. В списке сегментов
(левая область главного окна ОРС-сервера, показанного на рис. 1.12)
появится имя созданного сегмента, например PLCNet_l, если логиче-
ский номер сегмента был равен 1. Щелкните правой клавишей мыши
на названии устройства и выберите строку «Создать теги автомати-
чески» в появившемся контекстном меню. В древовидном списке
появятся группы тегов с именами, соответствующими узлам данного
сегмента сети. При поочередном выборе каждой группы в правой об-
ласти главного окна программы будут отображаться списки перемен-
ных (тегов) каждого узла.
Шаг 11
Для просмотра значений переменных выбранного узла выбе-
рите строку «Монитор» меню «Вид». Во время постоянной рабо-
ты сервера, с которым взаимодействуют клиенты ОРС, включение
режима «Монитор» приводит к дополнительной нагрузке на сеть
69
РАЗРАБОТКА SCADA-СИСТЕМ
UltraNet, а также к увеличению потребления системных ресурсов
компьютера, на котором работает сервер.
Шаг 12
Если к компьютеру подключены дополнительные сегменты
UltraNet, повторите для них описанную выше операцию создания
устройств, задавая в настройках другие значения логического номе-
ра сегмента, а также идентификатора COM-порта или сокета IPX.
|econfig.acf - PLCNET ОРС вии|
Файл Добавить Правка Вид Справка
юРЫ У| Ц II ч
& КЗ PLCNet-1 Имя | Тип I Адрес | | Значение | _±J
С3 02 --F03 Плавающее32р 02.F03 -1 —I
Ь-О 03 _-F03_3 Плавающее32р 02.F03J3 1
--F04 Плавающее32р 02.F04 -1
_-F0<3 Плавающее32р O2.FO<3 -0.638227
_-F05 Плавающее32р 02.F05 1
_-F05_3 Плавающее32р O2.FO5_3 1
F06 Плавающее32р 02.F06 1
--F06_3 Плавающее32р O2.FO6_3 1
_-”F07 Плавающее32р 02.F07 -1
_-F07_3 Плавающее32р O2.FO7_3 1
--F08 Плавающее32р 02.F08 -1
_-F08_3 Плавающее32р 02.F08J3 1 -I
А л Л Л
±1 J
Г отовность 102 содержит 318 тегов
Рис. 1.12. Главное окно ОРС-сервера
Шаг 13
Для сохранения конфигурации сервера выберите строку «Со-
хранить» или «Сохранить как...» в меню «Файл». Последующие
запуски сервера будут производиться с автоматической загрузкой
последней сохраненной конфигурации.
Демонстрационная версия программы Fastwel PLCNET
ОРС-сервер не поддерживает сохранение и восстановление конфи-
гурации.
Изменение свойств сегментов, узлов и тегов
Имена тегов и узлов предопределены адресом узла и именем
переменной, заданным в проекте UltraLogik. При необходимости
имена сегментов, узлов, групп тегов и тегов можно изменить, вы-
брав соответствующий объект с выполнением команды «Свойства»
70
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
контекстного меню. В свойствах группы можно отредактировать
только имя.
Диалоговая панель настройки параметров тега показана
на рис. 1.13.
Рис. 1.13. Диалоговая панель настройки параметров тега
Для тега можно:
- задать новое имя,
- задать линейное преобразование (масштабирование),
- переопределить источник, то есть выбрать другую перемен-
ную UltraNet в качестве данного тега.
Создание групп тегов вручную
Для создания группы тегов вручную необходимо выполнить
следующие действия.
1. Выберите сегмент или узел сети, в которую войдет созда-
ваемая группа, в левой области главного окна программы.
2. Щелкните левой клавишей мыши на кнопке «Создать груп-
пу» |Ql панели инструментов программы. На экран монито-
ра будет выведена диалоговая панель «Свойства группы».
3. Введите имя группы и нажмите кнопку ОК диалоговой па-
нели.
71
РАЗРАБОТКА SCADA-СИСТЕМ
Создание тегов вручную
Для создания тегов вручную необходимо выполнить следую-
щие действия.
1. Выберите группу (узел сети), в которую войдет создавае-
мый тег, в левой области главного окна программы.
2. Щелкните левой клавишей мыши на кнопке «Создать тег»
панели инструментов программы. На экран монитора
будет выведена диалоговая панель «Свойства тега», пока-
занная на рис. 1.12.
3. В поле «Имя» диалоговой панели введите имя создаваемого
тега.
4. Нажмите кнопку «Выбрать», расположенную справа от поля
«Источник» диалоговой панели «Свойства тега». На экран
монитора будет выведена диалоговая панель настройки па-
раметров сегмента сети UltraNet, показанная на рис. 1.10
или рис. 1.11.
5. В левой области диалоговой панели UltraNet выберите узел
и переменную узла, доступ к которой должен выполняться
через создаваемый тег. После этого нажмите кнопку ОК ди-
алоговой панели. Диалоговая панель UltraNet будет закры-
та, а в поле «Источник» диалоговой панели «Свойства тега»
появится имя переменной, на которую указывает создавае-
мый тег.
6. Нажмите кнопку ОК диалоговой панели «Свойства тега».
В списке тегов выбранного узла сети главного окна про-
граммы появится имя созданного тега.
Счетчики пакетов
Для каждого созданного узла UltraNet всегда создаются два
диагностических тега с названиями _SuccesCount и _ErrorCount —
счетчик успешно посланных пакетов и счетчик ошибочных пакетов,
на которые не получен ответ. Теги доступны по чтению и записи.
Запись в счетчик приводит к сбросу его значения в 0. Счетчики мо-
гут использоваться клиентами ОРС для расчета показателя качества
связи с каждым узлом.
72
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
Рекомендации по работе с ОРС-сервером
Сеть UltraNet, хотя и является достаточно надежной, не обеспе-
чивает полной гарантии доставки сообщений. Это общее свойство
многих прикладных протоколов, используемых в промышленной
автоматизации, где, как правило, важнее своевременность достав-
ки, чем ее гарантия.
ОРС-сервер также не повторяет операций чтения или запи-
си в случае неудачи. Таким образом, при передаче в контроллеры
непериодических одноразовых данных (команд), необходимо на
прикладном уровне анализировать результат выполнения команды.
Например, читать некую переменную состояния из контроллера,
чтобы убедиться в поступлении команды в контроллер.
Нужно также учитывать, что сетевой обмен осуществляется
асинхронно относительно выполнения задач в контроллере, поэтому
нельзя рассчитывать на одновременное поступление в контроллер
одновременно посланных данных. Такие данные реально могут быть
посланы в разных пакетах. Более того, может оказаться, хотя это и ма-
ловероятно, что один из этих пакетов вообще не дойдет до назначения.
Рекомендуется также избегать осуществления подряд двух
и более прямых операций, например записи в один и тот же тег.
Это связано с тем, что сервер отвергает операцию над тегом, пока
над ним не завершена предыдущая операция. Поэтому из двух про-
изведенных подряд операций вторая, скорее всего, будет отвергнута.
Не рекомендуется в штатном режиме пользоваться режимом
«Монитор». Следует использовать его только с целью предвари-
тельной отладки, поскольку это приводит к лишней перегрузке сети
и затратам процессорного времени, особенно в проектах с большим
количеством переменных.
В сети PLCNET на базе RS-485 без особой необходимости
не рекомендуется увеличивать количество мастеров, так как сеть
становится менее устойчивой из-за большей вероятности потери
маркера и, соответственно, возрастания расхода времени на его
восстановление. При большом количестве активных узлов, то есть
узлов, осуществляющих чтение или запись сетевых переменных по
собственной инициативе, сеть на базе Ethemet/IPX является более
предпочтительным и надежным решением.
73
РАЗРАБОТКА SCADA-СИСТЕМ
В проектах для контроллеров не рекомендуется объявлять все
переменные «на всякий случай» сетевыми, поскольку это замедляет
считывание конфигурации контроллеров и, соответственно, увеличи-
вает время соединения с ними, а также контроллеров между собой.
Сервер позволяет работать одновременно с шестью сегмента-
ми сети Ultranet (4 RS-485 и 2 IPX). Однако никаких гарантий удов-
летворительной работы сервера и сети для произвольного проекта
с произвольным набором сегментов, узлов, переменных и аппарат-
ных средств дано быть не может, поскольку реальных вычислитель-
ных ресурсов и пропускной способности сетей может не хватить.
В больших проектах рекомендуется протестировать предпола-
гаемую конфигурацию аппаратных и программных средств и сете-
вую топологию. Это можно сделать до принятия решения о количе-
стве узлов, сегментов, рабочих станций и ОРС-серверов с помощью
демонстрационной версии сервера.
1.7. Работа с ОРС-сервером Fastwel PlcNet ОРС Server
Рассмотрим работу с Fastwel PlcNet ОРС Server (в дальнейшем
ОРС-сервер), начиная с его установки. На рис. 1.14 показано исход-
ное расположение папки с дистрибутивом ОРС-сервера. Название
папки выделено.
Рис. 1.14. Исходное расположение папки с дистрибутивом ОРС-сервера
74
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
На рис. 1.15 показано содержимое папки Fastwel PlcNet ОРС
Server. Здесь файл PLCNetOPC.exe и есть дистрибутив ОРС-сервера.
Рис. 1.15. Содержимое папки Fastwel PlcNet ОРС Server
Далее следует стандартный набор окон:
- лицензионное соглашение (нажмите кнопку Yes),
- выбор папки, куда будет установлен ОРС-сервер (лучше со-
гласиться с предложенным местом),
- ввод серийного номера (этот номер у вас должен быть обя-
зательно, и если его нет, то требуйте его у фирмы Fastwel).
После этого в папке C:\Program Files создается папка Fastwel
(рис. 1.16). В этой папке содержится папка PLCNet ОРС Server
(рис. 1.17).
Содержимое папки PLCNet ОРС Server показано на рис. 1.18.
Файл Plcnetopc.exe и есть ОРС-сервер.
75
РАЗРАБОТКА SCADA-СИСТЕМ
Рис. 1.16. Папка Fastwel в папке C:\Program Files
Fastwel ВНЕ
Рис. 1.17. Папка PLCNet ОРС Server в папке Fastwel
76
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
Рис. 1.18. Содержимое папки PLCNet ОРС Server
После запуска ОРС-сервера появляется заставка и меню (рис. 1.19)
Рис. 1.19. Заставка Fastwel PlcNet ОРС Server
77
РАЗРАБОТКА SCADA-СИСТЕМ
После выбора опции «Сегмент UltraNet» в меню «Добавить»
появляется диалоговое окно Ultra Net (рис. 1.20). В окне «СОМ-порт»
выбираем COM2, так как в нашем случае сеть подключается к ма-
стеру через порт COM2. Установим скорость обмена в 9 600 бит/с.
Нажимаем кнопку «Применить».
ОРС-сервер начинает искать узлы в сети. В нашем случае к
сети подключены два контроллера с сетевыми адресами FD и FE,
установленными с помощью DIP-переключателей. Сервер нашел
эти контроллеры (узлы), что показано на рис. 1.21. Выбираем кон-
троллер с адресом FE.
Рис. 1.20. Диалоговое окно Ultra Net
Нажимаем кнопку «Создать». После этого создается сегмент
сети с именем Segment 01, который содержит выбранный узел FE
(рис. 1.22). Здесь в окно выводятся имена всех сетевых перемен-
ных, зарегистрированных в программе, выполняемой в контроллере
с адресом FE. Нажимаем кнопку ОК.
Переходим к пункту меню «Добавить» и выбираем опцию «Со-
здать теги автоматически». Перед этим нужно не забыть выделить
значок UltraNet 1.
78
ГЛАВА 1. SCADA-системы в компьютерных распределенных системах управления
Рис. 1.21. Поиск узлов в сети ОРС-сервером
Рис. 1.22. Создание сегмента сети с именем Segment oi с выбранным узлом FE
79
РАЗРАБОТКА SCADA-СИСТЕМ
Поскольку обращение к данному узлу будет использоваться
часто, то лучше всего конфигурацию запроса сохранить в файле.
Для сохранения выбирается опция «Сохранить как» меню «Файл».
По умолчанию дается имя файла config.acf. В дальнейшем при
выборе другого узла имя файла нужно выбрать другим, например
configFD.acf и т. д.
Щелкаем правой кнопкой на значке UltraNet 1 в левой части
диалогового окна. Появляется контекстное меню. Выбираем опцию
«Свойства». Появляется окно UltraNet (рис. 1.23). Щелкнув мышью
на нужной переменной, например vxodl, в разделе «Переменная»
наблюдаем ее имя, тип, значение и качество ее наблюдения.
Рис. 1.23. Окно UltraNet
80
ГЛАВА 2.
Организация взаимодействия
программного обеспечения диспетчерского
и контроллерного уровней в компьютерных
распределенных системах управления
2.1. Структура компьютерной распределенной системы
управления с одним узлом на диспетчерском уровне
В небольших системах управления часто встречается ситуа-
ция, когда диспетчерский уровень представлен одним удаленным
компьютером или рабочей станцией, как это показано на рис. 2.1.
Этот компьютер должен выполнять функции мастера промыш-
ленной сети. Для этого на нем должно быть запущен ОРС-сервер.
В нашем случае этот Fastwel PLCNet ОРС Server фирмы Fastwel.
Если SCADA-система также располагается на мастере, то можно ор-
ганизовать ее программное взаимодействие с ОРС-сервером напря-
мую, минуя объект автоматизации. SCADA-система в программном
смысле является ОРС-клиентом ОРС-сервера, расположенного на
этом же компьютере. Она может самостоятельно считывать значения
тегов-переменных технологического процесса.
Теги поставляются в промышленную сеть контроллерами —
узлами сети. Контроллеры сгруппированы в формации, которые
называются сегментами. Таким образом, формируется иерархия:
сегмент узел тег, которая показана на рис. 2.2. В данной гла-
ве мы будем рассматривать вопросы проектирования простых
SCADA-систем, которые здесь получили название просмотрщиков
тегов. Основное внимание в этой главе уделено клиент-серверному
взаимодействию ОРС-сервера и просмотрщиков тегов.
Иерархии сегмент узел тег можно поставить в соответ-
ствие иерархию аппаратных средств КРСУ: СОМ-порт компью-
тера — мастера сети контроллер переменная в управляющей
программе контроллера.
81
Рис. 2.1. Структура компьютерной распределенной системы управления с одним узлом на диспетчерском уровне
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Рис. 2.2. Иерархия промышленной сети
2.2. Простейший просмотрщик тегов для промышленной
сети PLCNET
Просмотрщик тегов реализован в среде программирования
Delphi и представляет собой проект. Содержимое папки данного
проекта показано на рис. 2.3. Внешний вид формы приложения по-
казан на рис. 2.4. Этот же вид с поясняющими надписями приведен
на рис. 2.5.
Рис. 2.3. Папка проекта просмотрщика тегов
83
РАЗРАБОТКА SCADA-СИСТЕМ
Приложение содержит только один компонент Timerl, созда-
ваемый с помощью палитры компонентов. Остальные компоненты
создаются динамически во время работы приложения.
В приложении будут использованы три стандартных процедуры
FormCreate, FormClose, Timerl.Timer. Кроме этого будет использо-
вана функция GetltemType, которая используется в процедуре Timerl.
Timer и предназначена для определения типа тега по его значению.
В разделе описания констант имеется константа tegs=32, зада-
ющая число тегов, принимаемых из промышленной сети. В разделе
описания типов описывается тип TItem, задающий атрибуты тега.
К атрибутам тега относятся:
- ItemName: string — имя тега;
- ItemHandle: OPCHANDLE — уникальный идентификатор
тега;
- ItemType: TVarType — тип тега;
- Item Value: string — значение тега;
- ItemQuality: word — качество принятого из сети тега.
Рис. 2Л. Внешний вид формы приложения просмотрщика тегов
В разделе описания переменных описываются:
- четыре панели Panell...Panel4, в каждой из которых будут
расположены по 8 окон вывода типа TLabeledEdit;
84
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
- четыре массива til, tl2, tl3, tl4, каждый из которых состоит
из 8 окон вывода (компонентов типа TLabeledEdit);
- массив ms, содержащий информацию о всех 32 тегах;
- переменная Server: lOPCServer, представляющая собой ин-
терфейс ОРС-сервера;
- HR:HRESULT — переменная, отражающая успешность
выполнения той или иной операции с тегом или с сегмен-
том сети;
- Segment:IOPCItemMgt — интерфейс ОРС-сервера, позво-
ляющий выполнять определенные действия с тегом и сег-
ментом;
- SegmentHandle:OPCHANDLE — уникальный идентифи-
катор сегмента сети.
Функция Getltemlype(ltem Value: string): string; возвращает стро-
ку, в которой указан тип тега. Возвращаются следующие значения:
- Timer — переменная таймерного типа;
- Boolean — переменная логического типа;
- Float — переменная вещественного типа;
- Integer — переменная целого типа.
Окно типа TLabeledEdit вывода величины тега
Panell
Панель Panel!
Рапе14
Панель РапеВ
Рис. 2.5. Внешний вид формы приложения с пояснениями
85
РАЗРАБОТКА SCADA-СИСТЕМ
Процедура TMainForm.FormCreate(Sender:TObject) выпол-
няет:
- начальные настройки таймера;
- формирование заголовка формы;
- настройку высоты и ширины формы (они устанавливаются
во весь экран);
- установку свойства BorderStyle в состояние bsDialog, что
приводит к появлению в правом верхнем углу лишь одного
значка закрытия окна приложения; кроме этого будет ис-
ключена возможность по изменению размеров формы;
- установку в нуль значений Left и Тор у формы MainForm.
Выполняются действия по динамическому созданию и разме-
щению на форме четырех панелей Panell...Panel4, которые хорошо
видны на рис. 2.4. Затем динамически создаются и размещаются на
первой панели Panell восемь окон ввода/вывода типа TLabeledEdit
в два ряда по 4 окна в ряду. Аналогичным образом происходит рас-
положение окон на панелях Рапе12, Рапе13, Рапе14.
Необходимо отметить, что полное имя тега будет в общем слу-
чае записываться так: ИМЯ СЕГМЕНТА. СЕТЕВОЙ АДРЕС УЗЛА.
ИМЯ ПЕРЕМЕННОЙ.
Здесь:
- ИМЯ СЕГМЕНТА определяется ОРС-сервером;
- СЕТЕВОЙ АДРЕС УЗЛА определяется ОРС-сервером;
- ИМЯ ПЕРЕМЕННОЙ задается программистом при про-
граммировании контроллера (переменная должна иметь статус се-
тевой).
После создания панелей, окон вывода необходимо выполнить
действия по именованию окон в соответствии с именем тега, значе-
ние которого будет помещаться в это окно. Кроме этого заполняют-
ся имена тегов в массиве ms.
После выполняется запуск ОРС-сервера, добавление в него
сегмента ULTRANET_1 и 32 тегов с заданными именами. Добавле-
ние в ОРС-сервер i-ro тега выполняется инструкцией:
HR: = GroupAdditem (Segment, ms[i].ItemName, SegmentHandle,
VTEMPTY,
ms[i].ItemHandle, ms[i].ItemType).
86
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
При этом тегу с именем ms[i] .ItemName ставится в соответствие
индивидуальный идентификационный номер ms[i] .ItemHandle,
который будет затем использоваться при чтении его значения из
сети во время выполнения процедуры TMainForm.Timerl.Timer.
Выполняется контроль над этими операциями с возможностью вы-
хода, если эти операции не будут нормально завершены.
Процедура TMainForm.FormClose(Sender:TOject; var Action:
TClose Action) реализует действия по выключению ОРС-сервера.
Процедура TMainForm.Timerl.Timer (Sender:TOject) вы-
полняет действия по чтению значений тегов и записи их в соответ-
ствующие окна. Это выполняется в цикле и для i-ro тега выглядит
так:
HR: =ReadOPCG roup Item Value (Segment, ms[i] .ItemHandle,
ms[I].Item Value, ms[i].ItemQuality).
Здесь в поле ms [i].Item Value считывается из сети значение
тега, идентификационный номер которого до этого был занесен
в поле ms [i] .Item Handle в процедуре TMainForm.FormCreate.
Далее осуществляется цикл вывода значений всех 32 тегов
в окна вывода. Сначала заполняются 8 окон из массива til, затем
8 окон из массива tl2, и так до массива tl4. Если чтение тега сопро-
вождалось ошибкой, то в соответствующее окно выводится строка
«Ошибка чтения».
Программный код приложения приведен в листинге 2.1 и со-
держит все необходимые комментарии.
Листинг 2.1
unit Main;
interface
uses
Windows, Messages, Syslltils, Variants, Classes, Graphics,
Controls, Forms, Dialogs, ExtCtrls, OPCDA, OPCTypes, OPCUtils,
ComObj, ActiveX;
87
РАЗРАБОТКА SCADA-СИСТЕМ
type
TMainForm = class(TForm)
Timeri:TTimer; //таймер
procedure FormCreate(Sender: TObject); //открытие формы
procedure FormClose(Sender: TObject; var Action:
TCIoseAction);
//закрытие формы
//обработка сигнала таймера
procedure TimenTimer(Sender: TObject);
private
{Private declarations}
public
{Public declarations}
end;
function GetltemType(ltemValue:string):string;
//структура тега
//имя тега
//идентификационный номер тега
//тип тега (заранее неизвестен)
//значение тега
//качество приема тега по сети
const
п=8; //число тегов, выводимых на одну панель
tegs=32; //общее число тегов
type
Tltem=record
ltemName:string;
ltemHandle:OPCHANDLE;
ItemTypeiTVarType;
ltemValue:string;
ltemQuality:word;
end;
va r // объявление переменных
Main Form: TMainForm; //главная форма
Panel^Pane^Pane^PanelzpTPanel; //четыре панели
//32 окна, сгруппированные в четыре группы
tla/tl2/tl3/tl4:array[i..n] of TLabeledEdit;
wzh:integer;
ms:array[i..tegs] of Tltem;
ServerdOPCServer;
HR:HRESULT;
//массив тегов
//ОРС-сервер
//результат добавления сегмента
//или тега в ОРС-сервер
//сегмент сети
SegmentdOPCItemMgt;
SegmentHandle:OPCHANDLE;//идентификационный номер тега
88
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
implementation
[$R *.dfm]
//функция, возвращающая тип тега
function GetltemType(ltemValue:string):string;
var
i,s:byte;
begin
Result:='Timer'; //тег имеет тип Timer
if (UpperCase(ltemValue)=/TRUE/) or
(UpperCase(ltemValue)=/FALSE/) then
begin 1/тег имеет тип Boolean
Result:='Boolean';
exit;
end;
for i:=1 to Length(ltemValue) do
if (ltemValue[i]=7) or (ltemValue[i]=7) then
begin //тег имеет тип Float
Result:='Float';
exit;
end;
s:=o;
for i:=i to Length(ltemValue) do
if ltemValue[i] in [чо717273//Ч75///67778797-7+/] then
inc(s);
if s=Length(ltemValue) then
begin //тег имеет тип Integer
Result:='lnteger';
exit;
end;
end;
procedure TMainForm.FormCreate(Sender:TObject);
var
i:integer;
begin
//настройка таймера и свойств формы
Timen. Enabled :=false;
Timen. Interval :=iooo;
Caption:='Big Black Box Reader [Кафедра «Автоматизация
Машиностроения»]7;
89
РАЗРАБОТКА SCADA-СИСТЕМ
Width :=Monitor.Width;
Height: ^Monitor. Height;
BorderStyle:=bsDialog;
Left:=o;
Top:=o;
w:=ClientWidth;
h :=GI ientHeight;
//создание первой панели и задание ее свойств
with Paneli do
begin
Paneli:=TPanel.Create(Self);
Parent:=MainForm;
Width:=w;
Height:=round(h/4);
Left:=o;
Top:=O;
Bevel lnner:=bvl_owered; //у панели вдавленная рамка
BevelOuter:=bvl_owered; //у панели вдавленная рамка
end;
//создание второй панели и задание ее свойств
with Panel2 do
begin
Panel 2:=TPanel.Create(Self);
Parent:=MainForm;
Width:=w;
Height:=round(h/4);
Left:=o;
Top:=Height;
Bevel lnner:=bvl_owered;
BevelOuter:=bvl_owered;
end;
//создание третьей панели и задание ее свойств
with Рапе1з do
begin
Panel3:=TPanel.Create(Self);
Parent:=MainForm;
Width:=w;
Height:=round(h/4);
Left:=o;
Top:=2*Height;
Bevel lnner:=bvl_owered;
90
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
BevelOuter:=bvLowered;
end;
//создание четвертой панели и задание ее свойств
with Panels do
begin
Panel4:=TPanel.Create(Self);
Parent:=MainForm;
Width:=w;
Height:=round(h/4);
Left:=o;
Top:=3*Height;
Bevel lnner:=bvl_owered;
BevelOuter:=bvl_owered;
end;
//создание 8 окон типа TLabeledEdit и размещение их
//на первой панели
for i:=i to n do
begin
tli[i]:=TLabeledEdit.Create(Self); //создание окна
tli[i].Parent:=Paneli; Цу окна родителем является панель
tli[i].Width:=round(w/4); //ширина окна равна 1/4
//ширины панели
tli[i].Font.Size:=14; //размер шрифта, определяет высоту окна
tli[i].EditLabel.Font.Size:=14; //размер заголовка окна
tli[i].Color:=clBtnFace; //цвет фона окна (серый)
tli[i].ReadOnly:=true; //в окно информацию можно только
//выводить
if i<5 then //верхний ряд окон
begin
tli[i].Left:=(i-i)*tli[i].Width; //левый край i-го окна
tli[i].Top:=round(o.25*Paneli.Height); //верхi-го окна
end
else //нижний ряд окон
begin
tli[i].Left:=(i-i-4)*tli[i].Width; //левый край i-го окна
tli[i].Top:=round(o.75*Paneli.Height); //верх i-го окна
end;
end;
//создание 8 окон типа TLabeledEdit и размещение их
//на второй панели
for i:=i to n do
begin
91
РАЗРАБОТКА SCADA-СИСТЕМ
tl 2[i]:=TI_abeled Ed it.Create(Self);
tl2[i].Parent:=Panel2;
tl2[i]. Width :=round(w/4);
tl2[i].Font.Size:=i4;
tl 2[i]. EditLabel. Font.Size:=14;
tl2[i]. Colored Btn Face;
tl2[i].ReadOnly:=true;
if i<5 then
begin
tl2[i].Left:=(i-i)*tl2[i]. Width;
tl2[i]Jop:=round(o.25*Paneli. Height);
end
else
begin
tl2[i].Left:=(i-i-4)*tl2[i]. Width;
tl2[i]Jop:=round(o.75*Paneli. Height);
end;
end;
//создание 8 окон типа TLabeledEdit и размещение их
//на третьей панели
for i:=i to n do
begin
tl3[i]:=TLabeledEdit.Create(Self);
tl3[i].Parent:=Panel3;
tl3[i]. Width :=round(w/4);
tl3[i].Font.Size:=i4;
tl3[i].EditLabel.Font.Size:=i4;
tl3[i]. Colored Btn Face;
tl3[i].ReadOnly:=true;
if i<5 then
begin
tl3[i].Left:=(i-i)*tl3[i].Width;
tl3[i].Top:=round(o.25*Paneli. Height);
end
else
begin
tl3[i].Left:=(i-i-4)*tl3[i].Width;
tl3[i].Top:=round(o.75*Paneli. Height);
end;
end;
//создание 8 окон типа TLabeledEdit и размещение их
//на четвертой панели
92
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
for i:=i to n do
begin
tl4[i]:=TLabeledEdit.Create(Self);
tl4[i].Parent:=Panel4;
tl4fi].Width :=round(w/4);
tl4[i].Font.Size:=i4;
tl4[i]. EditLabel. Font.Size:=i4;
tl4[i].Color:=clBtnFace;
tl4[i].ReadOnly:=true;
if i<5 then
begin
tl4[i].Left:=(i-i)*tl4[i].Width;
tl4[i].Top:=round(o.25*Paneli. Height);
end
else
begin
tl4[i].Left:=(i-i-4)*tl4[i]. Width;
tl4[i].Top:=round(o.75*Paneli. Height);
end;
end;
//создание имен тегов в массиве ms и перенос этих имен
//на панели
for i:=i to 8 do
begin
mstiJ.ltemNamei^ULTRANET-i.FE.MOTOR'+lntToSt^i);
tli[i]. EditLabel.Caption:=ms[i]. Item Name;
end;
for i:=9 to 16 do
begin
mstiJ.ltemNamei^ULTRANET.i.FE.M'+lntToSt^i);
tl2[i-8]. EditLabel.Caption :=ms[i]. Item Name;
end;
for i:=i7 to 24 do
begin
ms[i]. Item Names'Ll LTRANET_i.FE.Vxod/+lntToStr(i-i6);
tl3[i-i6]. EditLabel. Caption:=ms[i]. Item Name;
end;
for i:=25 to 32 do
begin
ms[i]. Item Names'Ll LTRANET_i.FE.Strob/+lntToStr(i-24);
tl4[i-24]. EditLabel.Caption :=ms[i]. Item Name;
end;
93
РАЗРАБОТКА SCADA-СИСТЕМ
И запуск Fastwel PLCNet ОРС-сервера
Server:=CreateComObject(ProglDToClasslD('Fastwel.PLCNetOPC/))
as lOPCServer;
//добавление в ОРС-сервер сегмента ULTRANET_i
HR:=ServerAddGroup(Server/ULTRANET_i/,true,500,о,Segment,
SegmentHandle);
if Failed(HR) then //сегмент с таким именем отсутствует
begin
ShowMessage('Oi_LJM6i<a добавления сегмента UltraNet/);
Application.Terminate; //закрытие приложения
end;
//добавление в ОРС-сервер32 тегов
for i:=i to tegs do
begin
HR:=GroupAddltem(Segmentzms[i]. Item Name,SegmentHandle,
VT_EM PTY, ms[i]. Item Handle, ms[i].ltemType);
if Failed(HR) then //такого тега нет
begin
ShowMessage('Oi_LJM6i<a добавления тега/);
Application.Terminate; //закрытие приложения
end;
end;
Timeri.Enabled:=true; //включить таймер
end;
//действия, выполняемые при закрытии формы
procedure TMainForm.FormClose(Sender:TObject; var Action:
TCIoseAction);
begin
Server:=nil; //выключить ОРС-сервер
end;
//чтение значение тегов из промышленной сети и вывод
И их значений в соответствующие окна соответствующим
//цветом
procedure TMainForm.TimenTimer(Sender:TObject);
var
i:integer;
begin
for i:=i to tegs do
begin
94
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//чтение i-го тега из сети
HR: = ReadOPCG roup Item Vai ue(Segmentzms[i]. Item Ha nd lezms[i].
Item Value, ms[i].ltemQuality);
if Succeeded(HR) then //тег прочитался нормально
begin
//теги с i-го по 8-и
if i<9 then
begin
tli[i].Font.Color:=clGreen;
if ms[i].ltemValue='False' then //тег имеет тип Boolean
tli[i]. Font.Colored Red;
if GetltemType(ms[i].ltemValue)='Float'
//тег вещественного типа
then
//вывод значения тега в соответствующее окно
tli[i].Text:=FloatToStrF(StrToFloat(ms[i]. Item Vai ue)zfffixedzi5z7)
else //теги типа Boolean, Integer, Timer
tli[i].Text:=ms[i]. Item Value;
end;
//теги с 17-го no 24-й
if (i>8) and (i<iy) then
begin
tl2[i-8].Font.Color:=clGreen;
if ms[i].ltemValue='False' then
tl2[i-8].Font.Colored Red;
if GetltemType(ms[i].ltemValue)='Float/
then
tl2[i-8].Text:=FloatToStrF(StrToFloat(ms[i]. Item Vai ue)zfffixedzi5z7)
else
tl2[i-8].Text:=ms[i]. Item Value;
end;
//теги с 17-го no 24-й
if (i>i6)and(i<25) then
begin
tl3[i-i6].Font.Color:=clGreen;
if ms[i].ltemValue='False' then
tl3[i-i6]. Font.Colored Red;
if GetltemType(ms[i].ltemValue)='Float'
then
tl3[i-i6].Text:=FloatToStrF(StrToFloat(ms[i]. Item Vai ue)zfffixedzi5z7)
else
95
РАЗРАБОТКА SCADA-СИСТЕМ
tl3[i-i6].Text:=ms[i].ltemValue;
end;
//теги с 25-го по32-й
if i>2Zpthen
begin
tl4[i-24]. Font.Color:=cl Green;
if msfiJ.ltemValue^'False' then
tl4[i-24]. Font.Colored Red;
if GetltemType(ms[i].ltemValue)=/Float/
then
tl4[i-24].Text:=FloatToStrF(StrToFloat(ms[i].ltemValue)/fffixed/i5/7)
else
tl4[i-24].Text:=ms[i].ltemValue;
end
end
else //при чтении тега произошла ошибка
begin
if i<9 then //длятегов ci-го no 8-и
begin
tli[i].Font.Color:=clRed; //красным цветом
tli[i].Text:=70un6Ka чтения7; //лучше бы этого не было
end;
if (i>8) and (i<iy) then //для тегов с 9-го noi6-u
begin
tl2[i-8]. Font.Colored Red;
tl2[i-8].Text:='OLun6Ka чтения7;
end;
if (i>i6)and(i<25) then //для тегов с 17-го по 24-й
begin
tl3[i-i6]. Font.Colored Red;
tl3[i-i6].Text:=7OLun6Ka чтения7;
end;
if i>24 then //для тегов с 25-го по32-й
begin
tl4[i-24]. Font.Colored Red;
tl4[i-24J.Text:=/Omn6i<a чтения7;
end;
end;
end;
end;
end.
96
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
2.3. Просмотрщик тегов в виде столбчатой диаграммы
Графическое представление той или иной информации об объ-
екте управления обладает, несомненно, большей ценностью, нежели
набор чисел или таблиц. Все это делает актуальным представление
значений тегов в графической форме, т. е. просмотр значений тегов.
Просмотрщик тегов реализован в виде приложения, разработанного
в среде Delphi. Содержимое папки, содержащей проект просмотр-
щика тегов, показано на рис. 2.6.
to Столбиковая диаграмма
Файл Правка Вид Избранное Сервис Справка
Назад ” Поиск Папки &
Адрес: =*> Р:\контооллео\Столбиковая диаграмма
Задачи для файлов и папок
Создать новую папку
О Опубликовать папку в вебе
Открыть общий доступ к этой
папке
Другие места
,-•) Контроллер
Мои документы
Общие документы
J Iron
> j Сетевое окружение
Подробно £
Столбиковая диаграмма
Папка с файлами
Изменен: 21 апреля 2004 г., 12:33
GgjAddUnit.^ddp
gi| AddUnit. ~dFm
В] AddUnit. ~pas
gj] AddUnit.dcu
j^AddUnit.ddp
j* AddUnit. dFm
AddUnit. pas
^7] AM. bmp
AutoSave, sav
^jDiagramms.^dpr
j^Diagramms.cFg
I^Diagramms.dof
kDiagramms.dpr
Diagramms.exe
gDiagramms.res
gi]Diagramms.tlb
j±f| Piagramms_TLB.dcu
*3 Key. bmp
|sl]Main.~ddp
gilMain.~dFm
Main. pas
J^Main.dcu
j±l]Main.ddp
/♦Main.dfm
if7 Main, pas
^jOPCPA.dcu
^OPCPA.pas
Ы] OPCtypes.dcu
^/OPCtypes.pas
i^OPCLltils.dcu
OPCutils.pas
3d Переход
Рис. 2.6. Содержимое папки, содержащей проект просмотрщика тегов
Рассмотрим пример, когда строятся восемь столбчатых диа-
грамм для тегов вещественного (Float) или целого типа (Integer),
принятых из сети Ultranet. Теги с этими именами должны входить
в список сетевых переменных контроллеров промышленной сети.
Работу приложения организуем следующим образом. Будут
использоваться две формы, работа каждой из которых описывается
в соответствующем модуле.
Первая форма AddForm (рис. 2.7) появляется на экране после
запуска приложения. На рис. 2.8 показана эта же форма с поясняю-
щими надписями.
97
РАЗРАБОТКА SCADA-СИСТЕМ
Рис. 2.7. Общий вид формы AddForm
Панель Panell Панель Panel?
Окно Node
Окно Srv
ввода имени
ОРС-сервера
Окно Sgt ввода
имени сегмента
intranet
ввода имени
узла
Логотип
Logo
Окно типа
TLabeledEdit
ввода имени тега
Кнопка ОК Кнопка OPCSnr
перехода к запуска ОРС-
MainFonn сервера
Рис. 2.8. Вид формы AddForm с пояснениями
Эта форма предназначена для задания таких параметров как:
- имя ОРС-сервера (Fastwel.PLCNetOPC);
- имя сегмента сети (Ultranet_l);
- сетевого адреса узла контроллера (FE);
- восьми имен тегов (Vxodl...Vxod8).
Имена тегов должны совпадать с именами сетевых перемен-
ных управляющей программы, записанной в память контроллера
с адресом FE и работающей в данное время.
98
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Форма ADDForm содержит также две кнопки:
- ОК, служащая для запуска второй (основной) формы
MainForm, на которой и реализовано построение столбча-
тых диаграмм;
- «Сервер», служащая для запуска Fastwel PLCNetOPC-
сервера.
Рассмотрим работу модуля AddUnit, который выполняет дина-
мическое создание формы AddForm и ее компонентов и определяет
ее работу В модуле AddUnit описаны четыре процедуры. Первая из
них TAddForm.FormCreate (Sender: TObject) выполняет действия:
- задание свойств формы AddForm;
- создание компонентов Panell и Рапе12;
- создание окон Srv (имя сервера), Sgt (имя сегмента сети),
Node (имя узла);
- создание восьми окон для ввода в них имен тегов (массив
mas);
- создание логотипа Logo;
- создание кнопок ок и «Сервер» и назначение процедур,
обслуживающих их нажатие;
- из файла Autosave.sav в окна Srv, Sgt, Node и окна из мас-
сива mas загружаются имена сервера, сегмента, узла, тегов,
которые были сохранены в файле при предыдущем запуске
приложения.
Пример содержимого файла Autosave.save показан ниже.
Fastwel. PLCNetOPC
Ultra net_i
FE
Vxodi
Vxoch
Vxod3
Vxodzp
Vxods
Vxod6
Vxody
Vxod8
5
15 5
99
РАЗРАБОТКА SCADA-СИСТЕМ
15
5
15
5
15
5
15
5
15
5
15
5
15
Заполнение окон формы AddForm осуществляется из 11 верх-
них строчек. Остальные строчки, содержащие цифры, будут исполь-
зованы в модуле MainUnit, который будет рассмотрен ниже.
Процедура TAddForm.FormActivate(Sender: TObject), вы-
полняемая при активации формы AddForm, устанавливает фокус на
кнопке ОК.
Процедура TAddForm.OKClick(Sender: TObject) выполняет
действия по скрытию формы AddForm и вызову, а затем запуску
формы MainForm.
Процедура TAddForm.OPCSrvClick(Sender: TObject) создает
и запускает ОРС-сервер Server.
В листинге 2.2 приведен модуль AddUnit с необходимыми ком-
ментариями.
Листинг 2.2
unit AddUnit;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
Forms,
Dialogs, StdCtrls, ExtCtrls, ComObj, OPCDA, OPCTypes, OPCUtils;
type
100
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
TAddForm = class(TForm)
procedure FormCreate(Sender: TObject); //реакция на создание
//формы
//реакция на активизацию формы
procedure FormActivate(Sender: TObject);
procedure OKCIick(Sender: TObject); //реакция на щелчок
//на кнопке ОК
//реакция на щелчок на кнопке «Сервер»
procedure OPCSrvClick(Sender: TObject);
private
{Private declarations}
public
{Public declarations}
end;
const
n=8; //число тегов
var
AddForm: TAddForm; //дополнительная форма
//панели для расположения на них других компонентов
Paneli, Panel 2:ТРапе1;
//кнопки ОК и «Сервер» вызова главной формы и запуска сервера
//PLCNetOPC
OKzOPCSrv:TButton;
background:TColor; //цвет фона
Logo:Tlmage; //логотип картинки
//окна для вывода имен сервера, сегмента и узла
SrvzSgtzNode:TLabeledEdit;
mas:array of TLabeledEdit; //массив для вывода тегов
implementation
uses Main; //подключение модуля главной формы
{$R *.dfm}
//процедура создания дополнительной формы
procedure TAddForm. FormCreate(Sender: TObject);
var
i:integer; //счетчик цикла
f:TextFile; //файловая переменная
s:string; //переменная для хранения
101
РАЗРАБОТКА SCADA-СИСТЕМ
//считанного из файла текста
begin
//настройки дополнительной формы
background:=RGB(ioozi5Oz2oo); //установка цвета фона
AddForm.Width:=Monitor.Width div 2; //установка ширины формы
AddForm.Height:=Monitor.Height div 3;
//установка высоты формы
//установка позиции формы на дисплее
AddForm. Position:=poScreenCenter;
//установка заголовка формы
AddForm.Caption ^'Настройка ОРС-сервера7;
//установка стиля границ формы
Add Form. BorderStyle:=bsSingle;
//установка разрешенных кнопок на форме
Add Form. Borderlcons:=[biSystem Menu];
AddForm.Color:=background; //установка цвета формы
//создание панели, на которой расположены окна вывода
//имен сервера, сегмента и узла
Paneli:=TPanel.Create(Paneli); //создание панели
Paneli.Parent:=AddForm; //родитель панели
Paneli.Top:=5; //ордината левого верхнего угла панели
Paneli.l_eft:=5; //абсцисса левого верхнего угла панели
Paneli.Width:=AddForm.Width-15; //ширина панели
Paneli.Height:=6o; //высота панели
//установка стиля внутренней границы панели
Paneli. Bevel lnner:=bvRaised;
//установка стиля внешней границы панели
Paneli. BevelOuter:=bvl_owered;
Paneli.Color:=background; //цвет панели
//создание панели, на которой расположены окна вывода
//имен тегов
Panel2:=TPanel.Create(Panel2); //создание панели
Panel2.Parent:=AddForm; //родитель панели
//ордината левого верхнего угла панели
Panel2.Top:=Paneli.Height+5;
Panel 2. Left:=5; //абсцисса левого верхнего угла панели
Panel2.Width:=AddForm.Width-i5; //ширина панели
Panel2.Height:=ioo; //высота панели
102
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//установка стиля внутренней границы панели
Panel2. Bevel lnner:=bvRaised;
//установка стиля внешней границы панели
Panel2.BevelOuter:=bvl_owered;
Panel2.Color:=background; //цвет панели
//создание окна для вывода имени сервера
Srv:=TI_abeledEdit.Create(Srv); //создание компонента
Srv.Parent:=Paneli; //родитель компонента
Srv.Top:=25; //ординаты левого верхнего угла компонента
Srv.l_eft:=i5; //абсцисса левого верхнего угла компонента
Srv.AutoSize:=false; //авторазмер компонента
Srv.Font.Size:=io; //размер шрифта компонента
Srv.Height:=2O; //высота компонента
Srv.Width:=Paneli.Width div 3 -20; //ширина компонента
Srv.EditLabel.Captioni^'OPC-Server'; //заголовок компонента
Srv.Text^'Fastwel.PLCNetOPC'; //свойство text компонента
S rv. Ed it La be I. Font. Col or:=cl Wh ite; //цвет шрифта компонента
//создание окна для вывода имени сегмента
Sgt:=TLabeled Edit.Create(Sgt); //создание компонента
Sgt.Parent:=Paneli; //родитель компонента
Sgt.Top:=25; //ордината левого верхнего угла компонента
Sgt.Left:=Srv.Left+Srv.Width+i5; //абсцисса левого верхнего
//угла компонента
Sgt.AutoSize:=false; //авторазмер компонента
Sgt.Font.Size:=10; //размер шрифта компонента
Sgt.Height:=20; //высота компонента
Sgt.Width:=Paneli.Width div 3 -20; //ширина компонента
II заголовок компонента
Sgt. EditLabel. Caption :='Сегмент Ultranet7;
Sgt.Text:='Ultranet_i'; //свойство text компонента
Sgt.EditLabel.Font.Color:=clWhite;//цвет шрифта компонента
//создание окна для вывода имени узла
Node:=TLabeledEdit.Create(Node); //создание компонента
Node.Parent:=Paneli; //родитель компонента
Node.Top:=25; //ордината левого верхнего угла компонента
Node.Left:=Sgt.Left+Sgt.Width+i5; //абсцисса левого верхнего
//угла компонента
Node.AutoSize:=false; //авторазмер компонента
103
РАЗРАБОТКА SCADA-СИСТЕМ
Node.Font.Size:=io; //размер шрифта компонента
Node.Height:=2O; //высота компонента
Node.Width:=Paneli.Width div 3 -20; //ширина компонента
Node.EditLabel.Caption:=/Узeл/; //заголовок компонента
Node.Text:=TEZ; //свойства text компонента
//цвет шрифта компонента
Node. EditLabel. Font.Colored White;
SetLength(maszn); //длина динамического массива
//создание окон для вывода имен тегов
for i:=0 to n-i do
begin
mas[i]:=TLabeledEdit.Create(mas[i]); //создание компонента
mas[i].Parent:=Panel2; //родитель компонента
mas[i].AutoSize:=false; //авторазмер компонента
mas[i].Width:=Раnel2.Width div 4 -5*5; //ширина компонента
mas[i].Height:=2O; //высота компонента
//цвет шрифта компонента
mas[i].EditLabel. Font. Color:=cl White;
if i<=3 then //верхний ряд окон
begin
//ордината левого верхнего угла компонента
mas[i].Top:=25;
//абсцисса левого верхнего угла компонента
mas[i].Left:=2o+i*mas[i].Width+2o*i;
end
else //нижний ряд окон
begin
//ордината левого верхнего угла компонента
mas[i].Top:=7O;
//абсцисса левого верхнего угла компонента
mas[i].Left:=204<i-4)*mas[i].Width+20*(i-4);
end;
//заголовок компонента
mas[i].EditLabel.Caption:='Kai-^ 4lntToStr(i+i);
//свойство text компонента
mas[i].Text:=/Vxod/+lntToStr(i+i);
mas[i].Font.Size:=io; //размер шрифта компонента
end;
//создание логотипа
Logo:=Tlmage.Create(Logo); //создание компонента
104
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Logo.Parent:=AddForm; //родитель компонента
Logo.Width:=ioi; //ширина компонента
l_ogo.Height:=5i; //высота компонента
Logo. Left: =7; //абсцисса левого верхнего угла компонента
//ордината левого верхнего угла компонента
Logo.Top:=Panel2.Top+Panel2.Height+io;
Logo. Picture. Load From FileCAM. bmp');
//загрузка картинки из файла
//создание кнопки ОК вызова главной формы
OK:=TButton.Create(OI<); //создание компонента
OK.Parent:=AddForm; //родитель компонента
О К. Са ptiоп:='О К'; //заголовок компонента
//абсцисса левого верхнего угла компонента
OK.Left:=Logo.Left+Logo.Left+Logo.Width+i55;
//ордината левого верхнего угла компонента
OK.Top:=AddForm.ClientHeight-OK. Height-15;
OK.OnCIick:=0KCIick; //определение процедуры OnClick
//компонента
//создание кнопки «Сервер» запуска сервера PLCNetOPC
OPCSrv:=TButton.Create(OPCSrv); //создание компонента
OPCSrv.Parent:=AddForm; //родитель компонента
OPCSrv.Caption^'CepBep'; //заголовок компонента
//абсцисса левого верхнего угла компонента
OPCSrv.Left-OK.Left+OK.Width+40;
//ордината левого верхнего угла компонента
OPCSrv.Top:=Add Form. ClientHeight-OPCSrv. Height-15;
//определение процедуры OnClickкомпонента
OPCSrv.OnClick:=OPCSrvClick;
//поиск файла AutoSave.savf в котором сохранялись
//настройки формы при предыдущей работе с приложением
Ци чтение текущих настроек сервера
if FileExistsCAutoSave.sav') then //если файл существует
begin
AssignFile(f,'AutoSave.sav'); И связь файловой переменной
//с файлом
Reset(f); //открытие файла для чтения
readings); //чтение имени сервера
Srv.Text:=s; //установка свойства text окна
readings); //чтение имени сегмента
Sgt.Text:=s; //установка свойства text компонента
105
РАЗРАБОТКА SCADA-СИСТЕМ
read I n(f,s); //чтение имени узла
Node.Text:=s; //установка свойства text компонента
for i:=o to n-i do //чтение имен тегов
begin
readings); //чтение имени тега
mas[i].Text:=s; //установка свойства text компонента
end;
CloseFile(f); //закрытие файла
end;
end;
//процедура активации дополнительной формы
procedure TAddForm.FormActivate(Sender:TObject);
begin
OK.SetFocus; //установка фокуса на кнопке ОК
end;
//процедура вызова главной формы
procedure TAddForm.OKCIick(Sender:TObject);
begin
AddForm.Hide; //скрытие дополнительной формы
Main Form. Show; // вызов главной формы
Run; //запуск процедуры Run главной формы
end;
//процедура запуска сервера PLCNetOPC
procedure TAddForm.OPCSrvClick(Sender:TObject);
begin
try
//создание ОРС-сервера
Server:=CreateComObject(ProglDToClasslD(Srv.Text)) as lOPCServer;
except //если произошла ошибка
//показ сообщения об ошибке
ShowMessage('He могу запустить сервер!!!7);
Server:=niI; //уничтожение сервера
end;
end;
end.
106
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Рассмотрим модуль Main, в котором реализуются действия по
отрисовке столбчатых диаграмм, каждая из которых соответствует
одной из сетевых переменных (тегов). На рис. 2.9 приведен внеш-
ний вид формы MainForm, работа которой определяется процеду-
рами и функциями модуля Main. На рис. 2.10 приведены необходи-
мые пояснения к компоновке формы MainForm.
Рис. 2.9. Общий вид формы MainForm
Из рис. 2.9 следует, что для изображения уровня величины на-
пряжения используется столбик из прямоугольников. Если каждому
прямоугольнику поставить в соответствие величину напряжения
в 0,2 В, а максимальное измеряемое напряжение составляет +5 В,
то для представления величины напряжения в +5 В потребуется
25 прямоугольников.
В раздел описания типов описан тип TItem, характеризующий
атрибуты тега. Этот тип представляет собой запись с полями, опре-
деляющими свойства тега, а также те компоненты, которые исполь-
зуются для его графического представления на экране.
107
РАЗРАБОТКА SCADA-СИСТЕМ
К последним относятся:
1. Компонент ItemImage:TImage, предназначенный для вывода
на его поверхность графического изображения столбчатой
диаграммы.
2. Компонент ItmValue:TEdit представляет собой окно выво-
да, расположенное под диаграммой и служащее для выво-
да в него числового значения, соответствующего величине
тега.
3. Компонент ItmLevel:TEdit представляет собой окно выво-
да, расположенного над диаграммой и служащее для выво-
да в него текстовой информации, отражающей нахождение
величины тега в заданных пределах (допуске): «норма»,
«выше нормы», «ниже нормы». Слово «норма» будет окра-
шено зеленым цветом, слова «выше нормы» — красным,
слова «ниже нормы» — желтым.
4. Компонент ItmDown:TTrackBar представляет собой дви-
жок, с помощью которого мы будем устанавливать нижнюю
границу изменения величины тега. Этот компонент будет
располагаться справа от диаграммы.
5. Компонент ItmUp: TTrackBar представляет собой дви-
жок, с помощью которого мы будем устанавливать верх-
нюю границу изменения величины тега. Этот компо-
нент расположен справа от диаграммы над компонентом
ItmDown:TTrackBar.
6. Компонент Panel:TPanel представляет собой компонент, на
котором будут располагаться все компоненты, рассмотрен-
ные выше.
7. Поля Up и Down типа real предназначены для хранения
нижней и верхней границ изменения величины тега. Рас-
смотренные выше компоненты также представляют собой
поля записи TItem.
108
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Рис. 2.10. Форма MainForm с пояснениями
В разделе описания переменных даны переменные, используе-
мые в данном приложении.
Функция GetItemType(Item Value:string):string предназна-
чена для того, чтобы по значению переменной определять ее тип.
Работа этой функции была рассмотрена ранее (просмотрщик 32 те-
гов).
Процедура Run запускает сервер, добавляет в него сегмент
Ultranetl и восемь тегов. Каждый из этих этапов контролируется.
Если возникает ошибка, выполняется переход к форме AddForm.
Если все нормально, то включается таймер Timerl.
Процедура Diagramma (u:real; number:integer) выполняет
отрисовку диаграммы для канала number+1. Здесь в качестве пара-
метров используются переменные:
- и — величина напряжения (значение тега);
- number — номер канала.
109
РАЗРАБОТКА SCADA-СИСТЕМ
Сначала проверяется величина и тега. Если она меньше ниж-
ней границы, то выбирается желтый цвет закраски, и в окне вывода
ItmLevel данного тега выводится сообщение «ниже нормы». Ана-
логичным образом обстоят дела, если величина и лежит в заданном
допуске или превышает его. Затем выполняется отрисовка прямо-
угольника (индикатора), расположенного рядом с номером канала:
определяются координаты xl, у1 и х2, у2 верхнего левого и правого
нижнего углов. Затем он закрашивается выбранным цветом.
Определяется высота 1 отдельного прямоугольника шкалы ди-
аграммы путем вычисления высоты всей шкалы, вычитания из нее
24 промежутков между прямоугольниками (величина промежутка
составляет 5 пикселей) и деления результата на число прямоуголь-
ников (25). Вычисления выполняются по формуле:
1 = (h - (nn - 1) х 5) / nn.
Здесь:
h — высота шкалы диаграммы;
nn — число прямоугольников в шкале диаграммы;
nn - 1 — число промежутков между прямоугольниками в шкале.
Затем определяется число j закрашенных прямоугольников по
формуле:
j = trunk (u/s).
Здесь:
trunk — целая часть;
и — измеряемое напряжение;
s — цена деления.
Закраска прямоугольников идет снизу вверх, т. е. начинается
от О В. Далее в цикле осуществляется вывод на экран закрашенных
прямоугольников. При этом вычисляются координаты xl, yl, х2, у2,
их углов и используется процедура Rectangle.
Далее выполняется выбор цвета заливки верхних незакрашен-
ных прямоугольников шкалы и отрисовка этих прямоугольников.
После этого вычисляются координаты углов прямоугольника, кото-
рый соответствует части напряжения и, не имеющей возможности
отразиться в целом прямоугольнике по формуле:
110
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
UU = U - j X S.
Здесь:
и — измеряемое напряжение;
s — цена деления одного прямоугольника (0,2 В);
j — число целых прямоугольников, которые отражают измеря-
емое напряжение.
Затем эта часть uu прямоугольника закрашивается.
Выполняется нанесение рисок и чисел от 0 до 4 на шкалу диа-
граммы. Координата у риски с номером i (i = 0...4) определяется по
формуле:
y = h- ix(lx5 + rx5)-l.
Здесь:
h — высота компонента Itemlmage;
i — номер риски;
1 — высота прямоугольника в шкале;
г — расстояние между прямоугольниками.
В формуле учитывается то, что одному вольту шкалы соответ-
ствует 5 прямоугольников и 5 промежутков между ними, каждый из
которых равен 5 пикселям.
Процедура TMainForm.FormCreate(Sender: TObject)
Реализует действия по созданию и размещению компонентов
на главной форме. В начале процедуры реализуются действия по
назначению свойств самой формы:
- задается заголовок формы;
- задается стиль границ формы;
- устанавливаются разрешенные кнопки в правом верхнем
углу формы;
- устанавливается цвет формы и ее геометрические параме-
тры.
- динамически создаются окна для вывода даты и времени.
Далее динамически создаются восемь панелей, на которых
затем будут располагаться диаграммы. При этом задается длина
динамического массива ms, равная 8. Затем создаются панели,
111
РАЗРАБОТКА SCADA-СИСТЕМ
определяются их свойства. На них выводятся окна ItmValue и
ItmLevel для вывода числового значения тега и нахождения его
в допуске. Окно ItmValue расположено в нижней части панели,
а окно ItmLevel — в верхней части панели.
Далее динамически создается компонент для рисования
Itemimage и задаются его свойства.
Создаются движки ItmUp и ItmDown, которыми можно регу-
лировать верхний и нижний пределы изменения величины тега со-
ответственно.
Создается кнопка AddFormRun, предназначенная для запуска
формы AddForm, и задаются ее свойства. На форме MainForm эта
кнопка имеет рисунок в виде гаечного ключа.
Создается логотип Logo (рисунок), помещаемый в правый
верхний угол формы.
Из файла AutoSave.sav читаются значения верхних и нижних
границ изменения величины всех восьми тегов, и ползунки движков
устанавливаются в заданные положения.
Процедура TMainForm.FormClose(Sender: TObject; Var
Action: TClose Action)
Выполняет следующие действия:
- в файл AutoSave.sav записываются имена сервера, сегмен-
та, узла и 8 тегов;
- затем туда же заносятся верхние и нижние границы измене-
ния тегов (всего 16 чисел);
- останавливается таймер;
- уничтожается сервер;
- закрывается приложение.
Процедура TMainForm.Timerl.Timer(Sender: TObject)
Выполняет следующие действия:
- считывает системную дату и время и помещает их в окно
Date и Time соответственно;
- читает значение всех восьми тегов, качества их приема и от-
рисовывает их, каждый раз вызывая процедуру Diagramma;
теги могут иметь значения Float или Integer.
112
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Процедура TMainForm.TrackBarChange(Sender: TObject)
Вызывается, если произошло смещение с помощью указателя
мыши ползунка какого-либо из шестнадцати движков, представлен-
ных на форме.
Если номер (Tag) движка меньше или равен 7, то перемещался
ползунок одного из движков, задающих нижний уровень изменения
величины тега. При этом выполняются следующие действия:
- идентифицируется номер движка;
- проверяется уровень его установки и, если он превышает
уровень установки соответствующего движка установки
верхнего уровня величины тега, то они приравниваются
друг другу;
- вычисляется значение нижнего уровня Down тега по вели-
чине Trbar.Position.
Если номер движка превышает 7, то перемещался ползунок од-
ного из движков, задающих верхний уровень изменения величины
тега. Выполняются действия, аналогичные рассмотренным ранее.
Процедура TMainForm.AddFormRunClick(Sender: TObject)
Выполняет действия по скрытию главной формы MainForm,
выключению таймера, выключению ОРС-сервера и вызову формы
AddForm.
Процедура TMainForm.FormDestroy(Sender: TObject)
Выключает ОРС-сервер и уничтожает динамический массив ms.
Модуль Main с соответствующими комментариями приведен
в листинге 2.3.
Листинг 2.3
unit Main;
interface
uses
Windows, Messages, Syslltils, Variants, Classes, Graphics,
Controls, Forms,
Dialogs, OPCDA, OPCTypes, OPCUtils, ExtCtrls, StdCtrls,
ComObj,
113
РАЗРАБОТКА SCADA-СИСТЕМ
ActiveX, ComCtrls, Addllnit, Buttons, SConnect, DB, DBCIient,
MConnect;
type
TMainForm = class(TForm)
Timeri: TTimer; //таймер
//реакция на создание формы
procedure FormCreate(Sender: TObject);
//реакция на закрытие формы
procedure FormClose(Sender: TObject; var Action: TCIoseAction);
//реакция на сигнал с таймера
procedure TimenTimer(Sender: TObject);
//обработка изменения положения ползунка движка
procedure TrackBarChange(Sender: TObject);
//реакция на нажатие кнопки с гаечным ключом типа
//TSpeedButton
procedure AddFormRunClick(Sender: TObject);
//уничтожение MainForm
procedure FormDestroy(Sender: TObject);
private
{Private declarations}
public
{Public declarations}
end;
const
n=8; //число тегов (переменных)
nn=25; //число прямоугольников в диаграмме
//цена деления — число вольт, соответствующих
//одному прямоугольнику
S=0.2;
type
// тег
Tltem=record
ltemName:string; //имя тега
ltemHandle:OPCHANDLE; //хэндл тега
ltemType:TVarType; //тип тега
ltemValue:string; //величина тега
ltemQuality:word; //качество связи тега
ltemlmage:Tlmage; //компонент для рисования диаграммы
ltmValue:TEdit; //окно вывода величины тега
// окно вывода статуса тега
114
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Itm Level :TEd it;
И движок для изменения нижней границы тега
ItmDowmTTrackBar;
И движок для изменения верхней границы тега
ltmUp:TTrackBar;
Panel:TPanel; //панель для объединения компонентов
// в группу
Uр:real; //верхняя граница тега
Down:real; //нижняя граница тега
end;
function GetltemType(ltemValue:string):string;
procedure Run;
procedure Diagramma(u:real;number:integer);
var
background:TColor; //цвет фона
MainForm: TMainForm; //главная форма
ms:array of Tltem; //динамический массив тегов
//переменная, хранящая результат добавления сегмента, узла
//или тега в ОРС-сервер
HR:HRESULT;
//интерфейс, осуществляющий добавление и удаление тегов
// в сегмент
SegmentdOPCItemMgt;
SegmentHandle:OPCHANDLE; //хэндл сервера
DatezTime:TLabeledEdit; //окно вывода времени и даты
Add Form Run :TSpeed Button; //кнопка вызова настройки сервера
Logo:Tlmage; //логотип
//интерфейс, осуществляющий добавление и удаление
//сегментов в ОРС-сервер
ServerdOPCServer;
implementation
{$R *.dfm}
//функция, определяющая тип тега
function GetltemType(ltemValue:string):string;
var
i,s:byte;
begin
Result^'Timer';
if (UpperCase(ltemValue)=/TRUE/) or
115
РАЗРАБОТКА SCADA-СИСТЕМ
(UpperCase(ltemValue)=/FALSE/) then
begin
Result:='Boolean';
exit;
end;
for i:=1 to Length(ltemValue) do
if (ltemValue[i]=7) or (ltemValue[i]=7) then
begin
Result:='Float';
exit;
end;
s:=o;
for i:=i to Length(ltemValue) do
if ltemValue[i] in [^Д'/г'/з'Д'Д'/б','778797-'/+'] then
inc(s);
if s=l_ength(ltemValue) then
begin
Result:='lnteger';
exit;
end;
end;
//процедура создает ОРС-сервер и добавляет в него
//сегменты и теги
procedure Run;
var
i:integer; //счетчик цикла
begin
try
//создание сервера
Server:=CreateComObject(ProglDToClasslD(Srv.Text)) as
lOPCServer;
//если не удалось создать сервер, то выдача сообщения об ошибке
Except
ShowMessage('He могу запустить сервер!!!');
Server:=nil; //уничтожение сервера
MainForm.Hide; //скрытие главной формы
AddForm.Show; // вызов дополнительной формы
Exit; //выход из процедуры
end;
116
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//добавление сегмента в сервер
HR:=ServerAddGroup(Server,Sgt.Text,true,500, о, Segment, Segment
Handle);
if not Succeeded(HR) then //если произошла ошибка
begin
// показ сообщения об ошибке
ShowMessage('He могу добавить группу!!!7);
Server:=niI; //уничтожение сервера
MainForm.Hide; //скрытие главной формы
AddForm.Show; //вызов дополнительной формы
Exit; //выход из процедуры
end;
//добавление тегов в сегмент
for i:=o to n-i do
begin
//полное имя тега
ms[i]. Item Name:=Sgt.Text+'.'+Node.Text+'.'+mas[i].Text;
//добавление тега
HR:=GroupAddltem(Segment,ms[i].ltemName/SegmentHandle/VT_
EM PTY, ms[i]. Item Handle, ms[i].ltemType);
if not Succeeded(HR) then //если произошла ошибка
begin
//показ сообщения об ошибке
ShowMessage('He могу добавить переменную '+ms[i].ltemName+'!');
Server:=niI; //уничтожение сервера
Main Form. Hide; //скрытие главной формы
AddForm.Show; //вызов дополнительной формы
Exit; // выход из процедуры
end;
end;
MainForm.Timeri.Enabled:=true; //запуск таймера
end;
//процедура, рисующая диаграмму для канала
//с номером number+i
procedure Diagramma(u:real;number:integer);
var
i:integer; //счетчик цикла
j:integer; //число закрашенных прямоугольников в диаграмме
I:integer; //высота одного прямоугольника в пикселях
117
РАЗРАБОТКА SCADA-СИСТЕМ
//процент высоты закрашенной части прямоугольника
// от высоты прямоугольника в диаграмме
pdnteger;
Color:TColor; //цвет закрашенной части диаграммы
xizyizx2zy2:integer; //координаты прямоугольника
//напряжение, не отображаемое целым прямоугольником
uu:real;
begin
Color:=background; //установка цвета
if u<ms[number].Down then
begin //величина тега меньше нижней границы
//желтый цвет закрашенной части диаграммы
Color:=clYellow;
// вывод статуса
ms[number]JtmLevel.Text^'HИЖЕ НОРМЫ';
end;
//величина тега меньше верхней границы и не ниже нижней
//границы
if (u<ms[number].Up) and (u>=ms[number].Down) then
begin
//зеленый цвет закрашенной части диаграммы
Color:=clGreen;
ms[number].ltmLevel.Text:='HOPMA'; // вывод статуса
end;
if u>=ms[number].Up then
begin //величина тега выше верхней границы
//красный цвет закрашенной части диаграммы
Color:=cl Red;
// вывод статуса
ms[number].ltmLevel.Text:='BblLUE НОРМЫ';
end;
//установка цвета заливки
ms[number]. Item Image. Canvas. Brush. Color:=Color;
//абсцисса левого верхнего угла индикатора уровня тега
xi:=ms[number]. Item Image.Width-35;
//ордината левого верхнего угла индикатора уровня тега
yi:=5;
//абсцисса правого нижнего угла индикатора уровня тега
x2:=ms[number].ltemlmage.Width-5;
//ордината правого нижнего угла индикатора уровня тега
У2:~25;
118
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//отрисовка индикатора уровня тега
ms[number].ltemlmage.Canvas.Rectangle(xi/yi/x2/y2);
//установка цвета шрифта компонента
ms[number].ltmLevel.Font.Color:=Color;
//абсцисса левого верхнего угла прямоугольника в диаграмме
xi:=5;
//абсцисса правого нижнего угла прямоугольника в диаграмме
X2:=ms[number].Itemimage.Width div 4 +5;
//нахождение высоты прямоугольника в диаграмме
I :=(ms[n umber]. Item Image. Height-ms[number]. Itm Level. Top-
ms[number].ltmLevel.Height-(nn-i)*5) div nn;
//нахождение числа закрашенных прямоугольников в диаграмме
j:=trunc(u/s);
ifjoo then //есть хотя бы один закрашенный прямоугольник
//отрисовка закрашенных прямоугольников в диаграмме
for i:=i to j do
begin
//нахождение ординаты левого верхнего угла прямоугольника
// в диаграмме
yi:=ms[number]. Item Image. Height-i*l-5*(i-i);
//нахождение ординаты правого нижнего угла прямоугольника
// в диаграмме
y2:=ms[number].ltemlmage.Height-(i-i)*l-5*(i-i);
//отрисовка закрашенного прямоугольника в диаграмме
ms[number]. Item Image.Canvas. Rectangle(Rect(xizyizx2zy2));
end;
//установка цвета заливки верхних незакрашенных
//прямоугольников
ms[number]. Item Image. Canvas. Brush. Color: ^background;
//отрисовка незакрашенных прямоугольников
for i:=j+i to nn do
begin
//нахождение ординаты левого верхнего угла прямоугольника
// в диаграмме
yi:=ms[number]. Item Image. Height-i*l-5*(i-i);
//нахождение ординаты правого нижнего угла прямоугольника
// в диаграмме
y2:=ms[number]. Item Image. Height-(i-i)*l-5*(i-i);
//отрисовка закрашенного прямоугольника в диаграмме
ms[number].ltemlmage.Canvas.Rectangle(Rect(xizyizx2zy2));
end;
119
РАЗРАБОТКА SCADA-СИСТЕМ
//нахождение напряжения, которому соответствует часть
//прямоугольника
uu:=u-j*s;
if ии>о then //это напряжение больше нуля
begin
//нахождение процента высоты закрашенной части
//прямоугольника от высоты всего прямоугольника
p:=trunc(uu*ioo/s);
//установка цвета заливки
ms[number]. Item Image. Canvas. Brush. Color:=Color;
//нахождение ординаты левого верхнего угла
//закрашенной части в прямоугольнике
yi:=ms[number].Item Image.Height-j*l-5*j4runc(p*l/ioo);
//нахождение ординаты правого нижнего угла
//закрашенной части в прямоугольнике
y2:=ms[number]. Item Image. Height-j*l-5*j;
//отрисовка закрашенной части в одном прямоугольнике
ms[number].ltemlmage.Canvas.Rectangle(Rect(xizyizx2zy2));
// если разница между ординатами правого нижнего угла
Ци левого верхнего угла закрашенной части больше одного
//пикселя
if y2-yi>i then
begin
//установка цвета линии
ms[number]. Item Image. Canvas. Pen. Color:=Color;
//отрисовка линии на верху закрашенной части
//прямоугольника
ms[number].ltemlmage.Canvas.MoveTo(xi+izyi);
ms[number].ltemlmage.Canvas.LineTo(x2-izyi);
end;
end;
//установка цвета линий рисок
ms[number]. Item Image. Canvas. Pen. Colored White;
//установка цвета заливки
ms[number]. Item Image. Canvas. Brush. Color: ^background;
// вывод чисел и отрисовка рисок на диаграмме
for i:=o to 4 do
begin
//отрисовка одной риски на диаграмме
ms[number].ltemlmage.Canvas.MoveTo(x2zms[number]. Item Image.
Height-i*(l*5+5*5)-i);
120
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
ms[number].ltemlmage.Canvas.LineTo(x2+i5zms[number]. Item Image.
Height-i*(l*5+5*5)-i);
ms[number].ltemlmage.Canvas.TextOut(x2+5zms[number]. Item Image.
Height-(i*(l*5+5*5))-2izlntToStr(i)); // вывод одного числа
end;
И вывод чисел на движках изменения нижней и верхней границ
//величины тега
for i:=o to 5 do
begin
//вывод числа на движке изменения нижней границы величины тега
ms[number].Item Image.Canvas.TextOut((ms[number].ltemlmage.Width
div 4)*3+5zms[number].ltmDown.Top+ms[number].ltmDown.Height-
round(i*(ms[number].ltmDown.Height div 5 -2))-2izlntToStr(i));
//вывод числа на движке изменения верхней границы величины
// тега
ms[number].Item Image.Canvas.TextOut((ms[number].ltemlmage.Width
div 4)*з+5, ms[number]. Itm Up.Top+ms[number]. Itm Up. Height
round(i*(ms[number].ltmUp.Height div 5 -2))-2izlntToStr(i));
end;
end;
//процедура создания главной формы
procedure TMainForm.FormCreate(Sender: TObject);
var
i:integer; //счетчик цикла
j:integer;
f:TextFile; //файловая переменная
begin
background:=RGB(ioozi5Oz2oo); //установка цвета фона
//настройки главной формы
//заголовок главной формы
MainForm.Caption:='АПИ НГТУ, кафедра Автоматизации
Машиностроения. Столбиковые диаграммы7;
//установка стиля границ главной формы
Main Form. BorderStyle:=bsSingle;
//установка разрешенных кнопок в правом углу главной формы
Main Form. Borderlcons:=[biSystem Menu, biMinimize];
//установка цвета главной формы в цвет background
Main Form. Color: ^background;
//абсцисса левого верхнего угла главной формы
121
РАЗРАБОТКА SCADA-СИСТЕМ
MainForm. Left:=о;
//ордината левого верхнего угла главной формы
MainForm.Top:=o;
MainForm.Width:=Monitor.Width; //ширина главной формы
MainForm.Height:=Monitor.Height; //высота главной формы
//создание окна для вывода даты
Date:=TLabeledEdit.Create(Date); //создание компонента
Date.Parent:=MainForm; //родитель компонента
Date. Left:=5; //абсцисса левого верхнего угла компонента
Date.Top:=2O; //ордината левого верхнего угла компонента
Date.Height:=25; //высота компонента
Date.Font.Size:=i2; //размера шрифта компонента
Date.AutoSize:=false; //авторазмер компонента
Date.EditLabel.Caption:='flATA:'; //заголовок компонента
Date.Width:=MainForm.Width div 8 -5; //ширина компонента
Date.ReadOnly:=True; //установка свойства «только чтение»
//компонента
//цвет заголовка компонента
Date. EditLabel. Font. Colored White;
Date.Color:=background; //цвет компонента
//создание окна для вывода времени
Time:=TLabeledEdit.Create(Time); //создание компонента
Time.Parent:=MainForm; //родитель компонента
//абсцисса левого верхнего угла компонента
Time.Left:=MainForm.Width div 8 +5;
Time.Top:=2O; //ордината левого верхнего угла компонента
Time.Height:=25; //высота компонента
Time.Font.Size:=i2; //размер шрифта компонента
Time.AutoSize:=false; //авторазмер компонента
Time.EditLabel.Caption^'BPEMA:'; //заголовок компонента
Time.Width:=MainForm.Width div 8 -5; //ширина компонента
Time.ReadOnly:=True; //установка свойства «только чтение»
//компонента
//цвет заголовка компонента
Time. EditLabel. Font.Colored White;
Time.Color:=background; //цвет компонента
//создание 8 панелей на главной форме
SetLength(mszn); //длина динамического массива
for i:=oto n-i do //создание элементов динамического массива
122
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
begin
//установка верхней и нижней границ тега
ms[i].Uр:=4; //установка верхней границы тега
ms[i].Down:=2; //установка нижней границы тега
//создание панели на главной форме
ms[i]. Panel :=TPanel.Create(ms[i]. Panel); //создание
//компонента
ms[i].Panel.Parent:=MainForm; //родитель компонента
//ширина компонента
ms[i].Panel.Width:=(MainForm.Width-io) div 8;
//высота компонента
ms[i]. Panel. Height: Wain Form. Cl ientHeight-10-50;
//абсцисса левого верхнего угла компонента
ms[i]. Panel. Left:=i*ms[i]. Panel.Width+5;
//ордината левого верхнего угла компонента
ms[i].Panel.Top:=55;
//стиль внутренней границы компонента
ms[i]. Panel. Bevel lnner:=bvRaised;
//стиль внешней границы компонента
ms[i]. Panel. BevelOuter:=bvLowered;
ms[i].Panel.BevelWidth:=2; //толщина границы компонента
ms[i].Panel.Color:=background; //цвет компонента
//создание окна для вывода измеряемой величины
ms[i].ltmValue:=TEdit.Create(ms[i]. ItmValue); //создание
//компонента
ms[i].ItmValue.Parent:=ms[i].Panel; //родитель компонента
ms[i]. ItmValue. AutoSize:=false; //установка авторазмера
//компонента
ms[i].ltmVaiие.Width:=ms[i].Panel.Width-20; //ширина
//компонента
ms[i].ltmValue.Height:=25; //высота компонента
ms[i].ItmValue.Font.Size:=i2; //размер шрифта компонента
//абсцисса левого верхнего угла компонента
ms[i]. ItmValue. Left: =10;
//ордината левого верхнего угла компонента
ms[i].ltm Vai ue.Top:=ms[i]. Panel. Height-ms[i]. ItmValue. Height-10;
//установка свойства «только чтение» компонента
ms[i]. ItmValue. ReadOnly:=true;
ms[i].ItmValue.Color:=background;//цвет компонента
123
РАЗРАБОТКА SCADA-СИСТЕМ
//создание окна для вывода уровня сигнала
ms[i].ItmLevel:=TEdit.Create(ms[i].ItmLevel); //создание
//компонента
ms[i].ItmLevel.Parent:=ms[i].Panel; //родитель компонента
ms[i].ItmLevel.AutoSize:=false; //установка авторазмера
//компонента
//ширина компонента
ms[i]. Itm Level.Width :=ms[i]. Panel.Width-20;
ms[i].ItmLevel.Height:=25; //высота компонента
ms[i].ItmLevel.Font.Size:=io; //размер шрифта компонента
//абсцисса левого верхнего угла компонента
ms[i]. Itm Level. Left:=io;
//ордината левого верхнего угла компонента
ms[i]. Itm Level.Тор:=35;
//установка свойства «только чтение» компонента
ms[i]. Itm Level. ReadOnly:=true;
ms[i].ItmLevel.Color:=background; //цвет компонента
//создания компонента для рисования
//создание компонента
ms[i].ltemlmage:=Tlmage.Create(ms[i]. Item Image);
ms[i].Itemimage.Parent:=ms[i].Panel; //родитель компонента
//абсцисса левого верхнего угла компонента
ms[i]. Item Image. Left:=5;
//ордината левого верхнего угла компонента
ms[i].ltemlmage.Top:=5;
//ширина компонента
ms[i]. Item lmage.Width:=ms[i]. Panel. Width-10;
//высота компонента
ms[i]. Item Image. Height:=ms[i]. Panel. Height-
ms[i]. Itm Value. Height-25;
//цвет заливки компонента
ms[i]. Item Image.Canvas. Brush.Color:=background;
//закраска цветом фона компонента
ms[i]. Item Image.Canvas. FillRect(Rect(ozozms[i].
Item lmage.Widthzms[i]. Item Image. Height));
//толщина линии компонента
ms[i]. Item Image. Canvas. Pen. Width :=i;
//цвет линий компонента
ms[i]. Item Image.Canvas. Pen.Colored White;
//размер шрифта компонента
ms[i]. Item Image.Canvas. Font.Size:=i2;
//цвет шрифта компонента
124
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
ms[i]. Item Image. Canvas. Font. Colored White;
//вывод номера канала на компоненте
ms[i]. Item Image.Canvas.TextOut(5z5/KAHAJl 4lntToStr(i+i));
//создание движка для изменения верхней границы тега
ms[i].ltmUp:=TTrackBar.Create(ms[i].ltmUp); //создание
//компонента
ms[i].ltmUp.Parent:=ms[i].Panel; //родитель компонента
//установка типа ориентации компонента
ms[i].ltmUp.Orientation:=trVertical;
//ширина компонента
ms[i].ltmUp.Width:=ms[i].Panel.Width div 5;
ms[i]. ltmUp.Height:=(ms[i]. Item Image. Height-ms[i]. Itm Level.Top-
ms[i].ltmLevel.Height-10) div 2; //высота компонента
//абсцисса левого верхнего угла компонента
ms[i].ltmUp.Left:=ms[i].Panel.Width div 2 +5;
//ордината левого верхнего угла компонента
ms[i]. Itm Up.Top:=ms[i]. Itm Level. Top+ms[i]. Itm Level. Height+5;
ms[i].ltmUp.Frequency:=i; //цена деления компонента
//установка минимального значения тега
ms[i].ltmUp.Min:=o;
//установка максимального значения тега
ms[i].ltmUp.Max:=nn;
//толщина шкалы измерения компонента
ms[i].ltmUp.ThumbLength:=io;
//установка позиции ползунка компонента
ms[i]. Itm Up. Position :=round(ms[i]. Itm Up. Max- 4/s);
//установка идентификационного номера компонента
ms[i].ltmUp.Tag:=i+io;
//создание движка для изменения нижней границы тега
//создание компонента
ms[i]. Itm Down:=TTracl<Bar.Create(ms[i]. Itm Down);
ms[i].ltmDown.Parent:=ms[i].Panel; //родитель компонента
//установка типа ориентации компонента
ms[i]. Itm Down. Orientation :=trVertical;
//ширина компонента
ms[i].ltmDown.Width:=ms[i].Panel.Width div 5;
ms[i]. Itm Down. Height:=(ms[i]. Item Image. Height-
ms[i].ltmLevel.Top-ms[i].ltmLevel.Height-10) div 2;
//высота компонента
//абсцисса левого верхнего угла компонента
125
РАЗРАБОТКА SCADA-СИСТЕМ
ms[i].ltmDown.Left:=ms[i].Panel.Width div 2 +5;
//ордината левого верхнего угла компонента
ms[i].ItmDown.Top:=ms[iJ.Item Image.Height-ms[i].ItmDown.Height;
ms[i].ltmDown.Frequency:=i; //цена деления компонента
//установка минимального значения шкалы компонента
ms[i]. Itm Down. Min :=o;
//установка максимального значения шкалы компонента
ms[i]. Itm Down. Max:=nn;
//толщина шкалы измерения компонента
ms[i].ltmDown.ThumbLength:=io;
//установка позиции ползунка компонента
ms[i]. Itm Down. Position :=round(ms[i]. Itm Down. Мах-2/s);
//установка идентификационного номера компонента
ms[i]. Itm Down.Tag:=i;
//определение процедуры OnChange движков
ms[i]. Itm Down. OnChange:=Tracl<BarChange;
ms[i].ltmUp.OnChange:=Tracl<BarChange;
end;
//создание кнопки с гаечным ключом для показа настроек сервера
//создание компонента
Add Form Run :=TSpeed Button. Create(Add Form Run);
AddFormRun.Parent:=MainForm; //родитель компонента
AddFormRun.Width:=25; //ширина компонента
AddFormRun.Height:=25; //высота компонента
//абсцисса левого верхнего угла компонента
Add Form Run. Left:=Time. Left+Time.Width+5;
//ордината левого верхнего угла компонента
Add Form Run.Тор:=2О;
Add Form Run. Flat:=true; //установка прозрачности компонента
//загрузка картинки из файла
Add Form Run. Glyph. Load From File('Key. bmp');
AddFormRun.ShowHint:=true; //установка свойства «показ
//подсказки»
AddFormRun.Hint:=zHacTpoMKM сервера7; //установка свойства
// «подсказка»
//определение процедуры компонента
Add Form Run. OnCI iclc=Add Form RunClick;
//создание логотипа
Logo:=Tlmage.Create(Logo); //создание компонента
Logo.Parent:=MainForm; //родитель компонента
126
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Logo.Width:=Ю1; //ширина компонента
Logo.Height:=5i; //высота компонента
//абсцисса левого верхнего угла компонента
Logo. Left:=Main Form.Width-Logo.Width-15;
//ордината левого верхнего угла компонента
Logo.Top:=2;
Logo.Picture.LoadFromFileCAM.bmp'); //загрузка картинки
//из файла
//поиск файла AutoSave.sav и чтение из него бывших верхних
Ци нижних границ тега
if FileExistsCAutoSave.sav') then //если файл существует
begin
AssignFile(fzAutoSave.sav'); //связь файловой переменной
Це файлом
Reset(f); //открытие файла для чтения
for i:=o to 10 do //пропуск и строк в файле
readln(f);
//чтение нижней и верхней границ всех 8 тегов
for i:=o to n-i do
begin
readln(fj); //чтение верхней границы i-го тега
ms[i].ItmUр.Position: =j; //установка ползунка движка
// в позицию j
//установка верхней границы i-го тега
ms[i].Up:=(ms[i].ltmUp.Max-j)*s;
read I n(fzj); //чтение нижней границы i-го тега
//установка ползунка движка в позицию j
ms[i].ltm Down. Position :=j;
//установка нижней границы i-го тега
ms[i]. Down :=(ms[i].ltm Down. Max-j)*s;
end;
CloseFile(f); //закрытие файла
end;
end;
//процедура закрытия формы
procedure TMainForm.FormClose(Sender: TObject; var Action:
TCIoseAction);
var
f:TextFile; //файловая переменная
i:integer; //счетчик цикла
127
РАЗРАБОТКА SCADA-СИСТЕМ
//переменная для хранения выбранного действия пользователя
inf:Word;
begin
//вызов диалогового окна для закрытия формы
inf :=MessageDlg('Bbi yBepeHbi?'zmtlnformationz[mbYeszmbNo]zo);
//запись в файл текущих настроек сервера, а также верхних
//и нижних границ всех тегов
if inf=mrYes then //если нажата кнопка Yes
begin
AssignFile(fz'AutoSave.sav'); //связь файловой переменной
Rewrite(f);
writeln(f,Srv.Text);
writeln(f,Sgt.Text);
writeln(f,Node.Text);
for i:=o to n-i do
//с файлом
//перезапись файла
//запись имени сервера
//запись имени сегмента
//запись имени узла
//запись имен переменных (тегов)
writeln(fzmas[i].Text);
//запись верхней и нижней границ тегов
for i:=o to n-i do
begin
//запись верхней границы i-го тега
writeln(fzms[i].ltm Up. Position);
//запись нижней границы i-го тега
writeln(fzms[i].ltm Down. Position);
end;
CloseFile(f); //закрытие файла
Timeri.Enabled:=false;
Server:=nil; //уничтожение сервера
SetLength(mszo);
Action:=caFree; //разрешение на закрытие главной формы
Application.Terminate; //закрытие приложения
end
else
Action:=caNone;
end;
//отмена закрытия главной формы
//процедура, выполняющая чтение с сервера переменных,
//даты и времени
procedure TMainForm J"imeriTimer(Sender: TObject);
var
i:integer;
dt:TDateTime;
//счетчик цикла
//переменная, хранящая дату и время
128
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
begin
dt:=Now; //чтение даты и времени
//запись в файл Date, text текущей даты
Date.Text:=FormatDateTime('dd.MM.yyyy r/,dt);
//запись в файлТ1те.text текущего времени
Time.Text:=FormatDateTime(4hh:mm:ss/,dt);
//чтение значений тегов из ОРС-сервера
for i:=o to n-i do
begin
//чтение из сегмента Segment величины и качества связи тега
//схэндлом ItemHandle в переменные ItemValue и ItemQuality
HR: = ReadOPCG roup Item Vai ue(Segmentzms[i]. Item Ha nd lezms[i].
Item Value, ms[i]. ItemQuality);
if Succeeded(HR) then //если прочитали без ошибок
begin
if GetltemType(ms[i]. Item Value)='Float'then
begin
//если величина тега станет меньше ofooi
if StrToFloat(ms[i].ltemValue)<o.ooi then
ms[i].ltemValue:=/o/; //установка ItemValue в ноль
//округление величины тега
ms[i].ltmValue.Text:=FloatToStrF(StrToFloat(ms[i]. ItemValue),
fffixed,5,3);
// вызов процедуры рисования диаграммы i+i канала
Diagramma(StrToFloat(ms[i]. Item Vai ue),i);
end;
if GetltemType(ms[i]. Item Value)='lnteger'then
// вызов процедуры рисования диаграммы i+i канала
Diagramma(StrTolnt(ms[i]. Item Vai ue),i);
//округленние ItemValue
ms[i]. Item Vai ue:=ms[i]. Itm Value.Text;
end;
end;
end;
//процедура изменения верхних и нижних границ тега
procedure TMainForm.TrackBarChange(Sender: TObject);
var
trbar:TTrackBar; //движок, который сдвинули
begin
//определение из 16 движков одного, который сдвинули
129
РАЗРАБОТКА SCADA-СИСТЕМ
trbar: ^Sender as TTrackBar;
//ес/ш идентификационный номер компонента не больше 8
if trbar.Tag<=7 then
begin
//знак поставлен наоборот, так как отсчет чисел на движке
// идет сверху вниз, а у нас снизу вверх
if ms[trbar.Tag]. Itm Down. Position<=ms[trbar.Tag]. Itm Up. Position
then
//если ползунок движка нижней границы оказался выше
//верхней границы, то установка ползунка движка нижней
//границы равным верхней границе
trbar. Position :=ms[trbar.Tag]. Itm Up. Position;
//установка нижней границы измеряемой величины
ms[trbar.Tag].Down:=(ms[trbar.Tag].ltmUp.Max-trbar.Position)*s;
end
else
begin
//знак поставлен наоборот, так как отсчет чисел на движке
// идет сверху вниз, а у нас снизу вверх если ползунок движка
//верхней границы оказался ниже нижней границы
if ms[trbar.Tag-io].ltmUp.Position>=ms[trbar.Tag-
10].ItmDown.Position then
//установка ползунка движка верней границы равным нижней
//границе
trbar. Position :=ms[trbar.Tag-io]. Itm Down. Position;
//установка верхней границы измеряемой величины
ms[trbar.Tag-io].Up:=(ms[trbar.Tag-io].ltmDown.Max-
trbar.Position)*s;
end;
end;
//процедура вызова формы настроек сервера
procedure TMainForm.AddFormRunClick(Sender: TObject);
begin
MainForm.Hide;
Timeri. Enabled :=false;
Server:=nil;
AddForm.Show;
end;
//скрытие главной формы
//выключение таймера
//уничтожение сервера
// вызов дополнительной формы
И процедура уничтожения формы
procedure TMainForm.FormDestroy(Sender: TObject);
begin
130
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Server:=nil;
SetLength(mszo);
end;
end.
//уничтожение сервера
2.4. Просмотрщик тегов в виде
круговой диаграммы со стрелкой
Просмотрщик тегов выполнен в виде приложения на языке
Delphi. Папка, содержащая данный проект, приведена на рис. 2.11.
Проект содержит две формы. Внешний вид одной из них, AddForm,
приведен на рис. 2.12. Она ничем не отличается от формы AddForm,
работа которой рассмотрена в предыдущем разделе. Она предназна-
чена для выполнения следующих действий:
- ввода имен ОРС-сервера, сегмента сети, узла и тегов, значе-
ния которых необходимо просмотреть;
- перехода к главной форме MainForm с помощью кнопки ОК;
- запуска Fastwel PLCNet ОРС-сервера с целью предвари-
тельной его настройки.
Рис. 2.11. Папка проекта просмотрщика тегов
в виде круговой диаграммы со стрелкой
131
РАЗРАБОТКА SCADA-СИСТЕМ
Рис. 2.12. Внешний вид одной из форм проекта, AddForm
Внешний вид формы MainForm данного приложения показан
на рис. 2.13. Она предназначена для выполнения следующих дей-
ствий:
- установки с помощью движков верхней и нижней границ
изменения величины для каждого из восьми выбранных те-
гов;
- графической интерпретации величин тегов в виде круговых
диаграмм со стрелкой;
- вывода числовых значений тегов;
- вывода даты и времени;
- вывода статуса каждого тега: «норма», «ниже нормы»,
«выше нормы»;
- возврата к форме AddForm;
- закрытия работы приложения.
На рис. 2.14 приведен внешний вид формы MainForm, на ко-
тором показаны используемые при ее работе компоненты и графи-
ческие элементы. К компонентам относятся:
- окна вывода даты и времени Date и Time соответственно;
- кнопка AddFormRun с изображением гаечного ключа, слу-
жащая для перехода к форме AddForm;
- логотип Logo;
- восемь панелей Panel, на которых расположены остальные
компоненты и элементы;
132
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
- ДВИЖКИ ItmUp для установки верхних границ величин те-
гов;
- движки ItmDown для установки нижних границ величин
тегов;
- окна вывода Item Value величин тегов.
К элементам формы относятся:
- надписи с обозначением номера канала (тега);
- надписи с обозначением статуса тегов;
- круговые диаграммы с изображением оцифрованных шкал
и стрелок;
- левые и правые части индикаторов уровней тегов (эти ин-
дикаторы расположены слева и справа от круговой диаграм-
мы).
Цвет индикаторов характеризует статус тега: зеленый цвет —
в норме (в допуске), красный цвет — выше нормы, желтый цвет —
ниже нормы.
Рис. 2.13. Общий вид формы MainForm
133
РАЗРАБОТКА SCADA-СИСТЕМ
Необходимо отметить, что шкала каждой диаграммы окрашена
в разные цвета. Имеются области с желтым цветом, с зеленым цве-
том и с красным цветом.
Работа главной формы MainForm описана в модуле Main
(unit Main). Этот модуль содержит точно такие же процедуры,
что и модуль Main приложения, рассмотренного в предыдущем раз-
деле. Небольшие отличия в работе некоторых процедур отображены
в подробных комментариях к их работе.
Единственным существенным отличием модулей Main данно-
го приложения и приложения, рассмотренного в разделе 2.3 (постро-
ение столбчатых диаграмм), являются процедуры, выполняющие
графические построения. Для данного приложения это процедура
Diagramma. Она имеет два параметра:
- и — величина тега (0... 5);
- number — номер канала (тега).
величины тега
Панель Panel
Рис. 2.14. Форма MainForm с пояснениями
134
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Рассмотрим работу процедуры Diagramma более подробно.
Поскольку для отрисовки диаграммы используются довольно слож-
ные графические построения, то для их рассмотрения будут исполь-
зоваться рис. 2.15 и 2.16. Для графических построений использу-
ются переменные rl, ugl, xl, yl, х2, у2, хО, уО, хЗ, уЗ, х4, у4, гЗ,
графическая интерпретация которых показана на рис. 2.15 и 2.16.
Процедура начинается с определения цвета статуса тега и ин-
дикатора его уровня. В зависимости от нахождения тега в допуске
может быть выбран желтый, зеленый, либо красный цвет. Старый
статус тега стирается путем наложения на него прямоугольника
с цветом фона формы. Затем выводится новый статус.
После этого вычисляются координаты углов прямоугольника
(xl, yl, х2, у2), в которые будет вписываться диаграмма, а также ее
радиус хО по оси X и уО по оси Y. Величины хО и уО в нашем случае
одинаковы.
Поскольку диаграмма разбивается на ряд секторов, то число
их может быть выбрано произвольно. Однако желательно, чтобы
каждый сектор имел целое число градусов. Поэтому было выбра-
но число секторов, равное 20, т. е. угол одного сектора составляет
360° /20 = 18° (ugl = 18).
диаграмма
Рис. 2.15. Структура диаграммы для процедуры Diagramma
135
РАЗРАБОТКА SCADA-СИСТЕМ
Находятся координаты хЗ, уЗ, х4, у4 углов правой части ин-
дикатора уровня тега, и он отрисовывается цветом статуса. Далее
находятся такие же координаты для левой части индикатора уровня
тега, и он отрисовывается цветом статуса.
Как видно из рис. 2.13, вся диаграмма состоит из 20 элементов,
каждый из которых представляет собой концевую часть большого
(внешнего) сектора. Элемент диаграммы строится следующим об-
разом:
- строятся все 20 больших секторов (рис. 2.15), причем окра-
ска каждого из них зависит от того, в какую из трех зон до-
пуска он попал;
- на полученную картинку сверху накладывается круг, цвет
которого совпадает с цветом фона; круг есть суммарное
представление 20 малых внутренних секторов (рис. 2.15);
- в результате получается круговая диаграмма, каждый эле-
мент которой окрашен в свой цвет (желтый, зеленый, крас-
ный) в зависимости от нахождения элемента в зоне до-
пуска.
Отрисовка 20 больших секторов выполняется в цикле. Вы-
бор цвета закраски осуществляется путем сравнения величины ixs
с нижней ms [number] .Down и верхней ms [number] .Up грани-
цами допуска.
Здесь:
- i — номер сектора (i = 1.. .20);
- s — цена деления шкалы диаграммы (s = 5 / 20 = 0,25 В).
Построение закрашенных секторов иллюстрируется на рис. 2.16.
136
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Рис. 2.16. Построение закрашенных секторов диаграммы
Поскольку отрисовка одного сектора выполняется с помощью
процедуры Pie(xl, yl, х2, у2, хЗ, уЗ, х4, у4), то необходимо знать
все параметры этой процедуры. Координаты xl, у1 верхнего левого
угла прямоугольника, в который вписывается диаграмма, а также
координаты х2, у2 его нижнего правого угла, были определены ра-
нее.
Осталось определить координаты хЗ, уЗ начала сектора и х4,
у4 его конца. Естественно, без геометрических построений здесь
не обойтись. Приведем формулы, по которым рассчитывались эти
координаты:
x4i = xl + хО - round (хО х cos ((i - 1) х ug 1 х gr));
y4i = yl + уО - round (уО х sin ((i - 1) х ugl х gr));
x3i = xl + хО - round (xO x cos (i x ugl x gr));
y3i = yl + yO - round (yO x sin (i x ugl x gr)).
137
РАЗРАБОТКА SCADA-СИСТЕМ
Здесь:
- i — номер сегмента;
- х1 — расстояние левой стороны прямоугольника, в который
вписывается диаграмма, от левого края панели;
- round — функция округления до ближайшего целого числа;
- у1 — расстояние верхней стороны прямоугольника, в кото-
рый вписывается диаграмма, от верхнего края панели;
- уО = хО — радиус диаграммы;
- ugl = 360° /20 — угол, приходящийся на один сектор;
- gr = л /180° — величина одного градуса в радианах.
После отрисовки всех 20 секторов выполняется вывод на экран
окружности радиуса rl с цветом фона формы. Так на экране появ-
ляются 20 элементов, образующих шкалу диаграммы.
В цикле выполняется вывод цифр 0...5 на шкалы движков
установки нижней и верхней границ изменения величины тега,
а над движками выводятся надписи «Верхняя граница» и «Нижняя
граница».
В цикле на диаграмму наносятся риски, а затем — цифры от 0
до 4. Вывод этих цифр (оцифровка шкалы диаграммы) выполняет-
ся не в цикле, т. к. трудно соотнести координаты этих цифр между
собой.
Графические построения заканчиваются построением стрелки,
положение которой характеризует величину тега и. Стрелка строит-
ся в виде треугольника и выводится с помощью процедуры Polygon,
приспособленной для таких построений. Построение стрелки осу-
ществляется с ее острия, поэтому координаты острия стрелки фи-
гурируют в массиве mas координат стрелки два раза. Координаты
острия стрелки определяются по формулам:
х = х1 + хО - round (хО х cos ((360° х и / 5) х gr));
у = yl + уО - round (уО х sin ((360° х и / 5) х gr)).
Здесь использованы те же обозначения, что и в формулах,
приведенных ранее. Последней выводится небольшая окружность
в центре — ось стрелки.
Содержимое файла AutoSave.sav, используемого для хранения
имен сервера, сегмента сети, узла, тегов и позиций движков уста-
новки верхних и нижних границ величин всех тегов, точно такое
138
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
же, что и в просмотрщике, рассмотренном в предыдущем разделе
(столбчатые диаграммы).
Программный код модуля Main с необходимыми комментария-
ми приведен в листинге 2.4.
Листинг 2.4
unit Main;
interface
uses
Windows, Messages, Syslltils, Variants, Classes, Graphics, Controls,
Forms,
Dialogs, OPCDA, OPCTypes, OPCUtils, ExtCtrls, StdCtrls, ComObj,
ActiveX, ComCtrls, Addllnit, Buttons, DB, DBCIient, MConnect, SConnect;
type
TMainForm = class(TForm)
TimernTTimer; //таймер
//действия при создании формы
procedure FormCreate(Sender: TObject);
//действия при закрытии формы
procedure FormClose(Sender: TObject; var Action: TCIoseAction);
//реакция на сигналы таймера
procedure TimenTimer(Sender: TObject);
// реакция на изменения положения ползунков движков установки
границ
// тега
procedure TrackBarChange(Sender: TObject);
//действия, вызванные щелчком на кнопке с изображением
//гаечного ключа перехода к AddForm
procedure AddFormRunClick(Sender: TObject);
//действия при уничтожении формы
procedure FormDestroy(Sender: TObject);
private
{Private declarations}
public
{Public declarations}
end;
139
РАЗРАБОТКА SCADA-СИСТЕМ
const
n=8;
nn=2O;
5=0.25;
//число тегов
//число элементов в шкале диаграммы
// цена деления
type
// тег
Tltem=record
ltemName:string; //имя тега
ltemHandle:OPCHANDLE; //хэндл тега
ltemType:TVarType;
ltemValue:string;
ltemQuality:word;
ltemlmage:Tlmage;
ltmValue:TEdit;
ItmDowmTTrackBar;
//тип тега
//величина тега
//качество связи тега
//компонент для рисования
//компонент для вывода величины тега
// движок для изменения нижней
//границы тега
// движок для изменения верхней
//границы тега
//панель для объединения компонентов в группу
//верхняя граница тега
//нижняя граница тега
ltmUp:TTrackBar;
PanekTPanel;
Up:real;
Dowmreal;
end;
function GetltemType(ltemValue:string):string;
procedure Run;
procedure Diagramma(u:real;number:integer);
var
background:TColor;
Main Form: TMainForm;
ms:array ofTItem;
HR:HRESULT;
//цвет фона
//главная форма
//динамический массив тегов
//переменная, которая хранит результат
//операции
//интерфейс, с помощью которого осуществляется добавление
// тегов в сервер и их удаление
Segment: lOPCItemMgt;
SegmentHandle:OPCHANDLE;
DatezTime:TLabeledEdit;
Add Form Run :TSpeed Button;
//хэндл сервера
//окна вывода времени и даты
//кнопка «Сервер» вызова
//настройки сервера
140
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Logo:Tlmage; //логотип
//интерфейс, с помощью которого осуществляется добавление
// и удаление сегментов из ОРС-сервера
ServerdOPCServer;
implementation
{$R *.dfm}
//функция, определяющая тип тега
function GetltemType(ltemValue:string):string;
var
i,s:byte;
begin
Result:=Timer';
if (UpperCase(ltemValue)='TRUEl) or
(UpperCase(ltemValue)='FALSEl) then
begin
Result:='Boolean';
exit;
end;
for i:=i to Length(ltemValue) do
if (ItemVaIue[i]='.') or (ItemValuefiJ^1,1) then
begin
Result:='Float';
exit;
end;
s:=o;
for i:=1 to Length(ltemValue) do
if ltemValue[i] in [lol/ir/l2l/l3l/lzhl/l5l/l6l/l7l/l8l/l9l/l-l/l+l] then
inc(s);
if s=l_ength(ltemValue) then
begin
Result:='lnteger';
exit;
end;
end;
//процедура, выводящая на экран круговую диаграмму
И для тега с номером number+i; здесь и — величина тега
procedure Diagramma(u:real;number:integer);
const
//градус в радианах
gr=pi/i8o;
141
РАЗРАБОТКА SCADA-СИСТЕМ
var
//счетчик
i:integer;
//число градусов в одном элементе диаграммы
ugkinteger;
//внутренний радиус
ruinteger;
//ширина диаграммы
r2:integer;
//цвет индикатора уровня тега
Color:TColor;
//координаты левого верхнего угла индикатора уровня тега
// координаты левого верхнего угла прямоугольника, в который
//вписывается диаграмма
xizyi:integer;
//координаты правого нижнего угла индикатора уровня тега
//координаты правого нижнего угла прямоугольника, в который
//вписывается диаграмма
X2zy2:integer;
//координаты начальной точки сектора
x3zy3:integer;
//координаты конечной точки сектора
xz^yzpinteger;
//координаты центра диаграммы
xozyo:integer;
//переменные для отрисовка рисок на диаграмме
xzy:integer;
//переменная для вывода текста
ss:string;
//массив для отрисовка стрелки
mas:array[o..3] ofTPoint;
begin
//ширина линии
ms[number]. Item Image. Canvas. Pen. Width =2;
//установка цвета
Color:=background;
//если величина тега меньше нижней границы
if u<ms[number].Down then
begin
//желтый цвет закрашенной части диаграммы
Color:=clYellow;
142
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//установка статуса тега
ss-’НИЖЕ НОРМЫ1;
end;
//если величина тега меньше верхней границы и больше нижней
//границы
if (u<ms[number].Up) and (u>=ms[number].Down) then
begin
//зеленый цвет закрашенной части диаграммы
Color:=clGreen;
//установка статуса тега
ss:='HOPMA';
end;
//если величина тега выше верхней границы
if u>=ms[number].Up then
begin
//красный цвет закрашенной части диаграммы
Color:=cl Red;
//установка статуса тега
ss-’ВЫШЕ НОРМЫ1;
end;
//установка размера шрифта
ms[number]. Item Image.Canvas. Font.Size:=io;
//установка цвета заливки
ms[number]. Item Image. Canvas. Brush. Color:=background;
//установка цвета шрифта
ms[number].ltemlmage.Canvas.Font.Color:=Color;
//координата xi для прямоугольника, стирающего старый
//статус тега
xi:=ms[number].ltemlmage.Width-
ms[number].ltemlmage.Canvas.TextWidth(ss)-5;
//координата yi для прямоугольника, стирающего старый
//статус тега
yi:=5;
//отрисовка прямоугольника, стирающего старый статус тега
ms[number].ltemlmage.Canvas.FillRect(Rect(ms[number]. Item Image.
Width div 2/yi/ms[number].ltemlmage.Width/yi+2o));
// вывод нового статуса тега
ms[number].ltemlmage.Canvas.TextOut(xizyizss);
//отрисовка индикатора уровня тега
//установка цвета заливки
143
РАЗРАБОТКА SCADA-СИСТЕМ
ms[number]. Item Image. Canvas. Brush. Color:=Color;
//установка цвета шрифта
ms[number]. Item Image.Canvas. Font.Colored White;
//координата yi для прямоугольника, в который вписывается
//диаграмма
yi:=20;
//координата у2 для прямоугольника, в который вписывается
//диаграмма
y2:=ms[number]. Item Image. Height-i5-ms[number]. ItmDown. Height-30-
ms[number].ltmUp. Height-15-15;
//радиус no оси у
yo:=(y2-yi) div 2;
//координата xi для прямоугольника, в который вписывается
//диаграмма
xi:=(ms[number],Itemimage.Width-2*yo) div 2;
//координата X2 для прямоугольника, в который вписывается
//диаграмма
X2:=ms[number], Item Image.Width-xi;
//радиус по оси х
xo:=(x2-xi) div 2;
//угол ugl, соответствующий одному элементу, здесь пп — число
//секторов
ugl:=round(36o/nn);
//отрисовка правой части индикатора уровня тега
//координата х верхнего левого угла правой части индикатора
//уровня тега
хз:=Х2-ю;
// координата у верхнего левого угла правой части индикатора
//уровня тега
y3:=yi+yo-4O;
//координата х нижнего правого угла правой части индикатора
//уровня тега
Х4:=Х2+2О;
// координата у нижнего правого угла правой части индикатора
//уровня тега
у4:=у1+уо+4О;
ms[number].ltemlmage.Canvas.Rectangle(Rect(x3/y3/xzh/yzh));
//отрисовка левой части индикатора уровня тега
//координата х верхнего левого угла левой части индикатора
//уровня тега
144
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
ХЗ:=Х1-2О;
И координата у верхнего левого угла левой части индикатора
//уровня тега
y3:=yi+yo-4O;
// координата х нижнего правого угла левой части индикатора
//уровня тега
Х4:=Х1+ю;
// координата у нижнего правого угла левой части индикатора
//уровня тега
у4:=у1+уо+4О;
ms[number].ltemlmage.Canvas.Rectangle(Rect(x3/y3/xzh/yzh));
//отрисовка элементов диаграммы
//отрисовка 20 больших (внешних) секторов
for i:=i to nn do
begin
//если i*s меньше нижней границы
if i*s<=ms[number].Down then
//сектор имеет желтый цвет
Color:=clYellow;
//если i*s меньше верхней границы и больше нижней границы
if (i*s<=ms[number].Up) and (i*s>ms[number].Down) then
//сектор имеет зеленый цвет
Color:=clGreen;
//если i*s больше верхней границы
if i*s>ms[number].Up then
//сектор имеет красный цвет
Col or:=cl Red;
//установка цвета заливки сектора
ms[number]. Item Image. Canvas. Brush. Color:=Color;
//вычисление координат сектора
//координата xj i-го сектора
x3:=xi+xo-round(xo*cos(i*ugl*gr));
//координатаyj i-го сектора
y3:=yi+yo-round(yo*sin(i*ugl*gr));
//координата х$ i-го сектора
x4:=xi+xo-round(xo*cos((i-i)*ugl*gr));
//координата у4 i-го сектора
y4:=yi+yo-round(yo*sin((i-i)*ugl*gr));
//отрисовка i-го элемента диаграммы
ms[number].ltemlmage.Canvas.Rie(xi/yi/x2/y2/x3/y3/xzh/y4);
end;
145
РАЗРАБОТКА SCADA-СИСТЕМ
//установка цвета заливки
ms[number].ltemlmage.Canvas.Brush.Color:=background;
//вычисление п
ri:=xo-2o;
//отрисовка внутреннего круга, в который входят все внутренние
//(малые) сектора
ms[number]. Item Image.Canvas. El lipse(xi+xo-ri,yi+yo-
ri,xi+xo+n,yi+y o+n);
//отрисовка чисел на шкалах движков изменения верхней и нижней
//границ
for i:=o to 5 do
begin
//отрисовка чисел на шкале движка изменения нижней границы
ms[number].ltemlmage.Canvas.TextOut(i*(ms[number]. Itm Down.
Width div 5 -2)4-2,ms[number].Itemimage.Height-15,IntToStr(i));
//отрисовка чисел на шкале движка изменения верхней границы
ms[number].ltemlmage.Canvas.TextOut(i*(ms[number].ltmllp.
Width div 5 -2)4-2,ms[number].Itemimage.Height-i5-ms[number].
Itm Down. Height-30, IntToStr(i));
end;
//вывод надписи над движком изменения нижней границы
ms[number].ltemlmage.Canvas.TextOut(5zms[number].ltemlmage.
Height-i5-ms[number].ItmDown.Height-15/ НИЖНЯЯ ГРАНИЦА1);
//вывод надписи над движком изменения верхней границы
ms[number].ltemlmage.Canvas.TextOut(5,ms[number]. Item Image.
Height-i5-ms[number].ltmDown.Height-3O-ms[number].ltmUp.
Height-15,1 ВЕРХНЯЯ ГРАНИЦА);
//отрисовка длинных рисок на диаграмме
//установка ширины длинных рисок на диаграмме
ms[number]. Item Image. Canvas. Pen. Width =2;
for i:=oto 4 do
begin
//вычисление координат начала и конца длинной риски
//координата х начала риски
x:=xi+xo-round(xo*cos(i*4*ugl*gr));
//координата у начала риски
y:=yi+yo-round(yo*sin(i*4*ugl*gr));
// перемещение указателя в точку (х,у)
ms[number].ltemlmage.Canvas.MoveTo(x,y);
//координата х конца риски
146
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
x:=xi+xo^ound((ri-5)*cos(i*4*ugl*gr));
И координата у конца риски
у: =yi+yo-rou nd((ri-5)*si n(i*4* ug I *g r));
//отрисовка риски
ms[number].ltemlmage.Canvas.LineTo(xzy);
end;
//установка размера шрифта
ms[number]. Item Image.Canvas. Font.Size:=i2;
// вывод цифр внутри шкалы диаграммы
//вычисление ширины диаграммы
Г2:=хо-Г1;
//отрисовка цифр о...4 внутри диаграммы (i — номер цифры)
//цифра о
i:=o;
//координата х цифры о
x:=xi+xomound(xo*cos(i*4*ugl*gr))+r2+5;
// координата у цифры о
y:=yi+yo+round(yo*sin(i*4*ugl*gr))-io;
// вывод цифры о на шкале диаграммы
ms[number]. Item Image.Canvas.TextOut(xzyzlntToStr(i));
// цифра i
inc(i);
//координата x цифры i
x:=xi+xo-round(xo*cos(i*4*ugl*gr));
// координата у цифры i
y:=yi+yo-round(yo*sin(i*4*ugl*gr))+r2+5;
// вывод цифры 1 на шкале диаграммы
ms[number].ltemlmage.Canvas.TextOut(xzyzlntToStr(i));
//цифра 2
inc(i);
//координата х цифры 2
x:=xi4o<o-round(xo*cos(i*4*ugl*gr))-r2-i5;
// координата у цифры 2
y:=yi+yo-round(yo*sin(i*4*ugl*gr))+5;
// вывод цифры 2 на шкале диаграммы
ms[number].ltemlmage.Canvas.TextOut(xzyzlntToStr(i));
// цифра з
inc(i);
// координата х цифры 3
x:=xi4o<o-round(xo*cos(i*4*ugl*gr))-r2-i5;
147
РАЗРАБОТКА SCADA-СИСТЕМ
// координата у цифры 3
y:=yi+yo^ound(yo*sin(i*4*ugl*gr))-r2-io;
И вывод цифры з на шкале диаграммы
ms[number].ltemlmage.Canvas.TextOut(xzyzlntToStr(i));
//цифра 4
inc(i);
//координата х цифры 4
x:=xi+xo^ound(xo*cos(i*4*ugl*gr))+5;
//координата у цифры 4
y:=yi+yo-round(yo*sin(i*4*ugl*gr))-r2-25;
// вывод цифры 4 на шкале диаграммы
ms[number]. Item Image.Canvas JextOut(xzyzlntToStr(i));
//отрисовка стрелки
//Г2 — радиус маленькой окружности в начале стрелки
Г2:=2;
//вычисление координат стрелки
//координата х острия стрелки
mas[o].x:=xi+xo^ound(xo*cos((36o*u/5)*gr));
//координата у острия стрелки
mas[o].y:=yi+yo-round(yo*sin((36o*u/5)*gr));
mas[i].x:=xi+xo^ound(r2*cos((36o*u/5+9o)*gr));
mas[i].y:=yi+yo-round(r2*sin((36o*u/5+9o)*gr));
mas[2].x:=xi+xo^ound(r2*cos((36o*u/5-9o)*gr));
mas[2].y:=yi+yo-round(r2*sin((36o*u/5-go)*gr));
//координата x острия стрелки
mas[3].x:=xi+xo^ound(xo*cos((36o*u/5)*gr));
//координата у острия стрелки
mas[3].y:=yi+yo-round(xo*sin((36o*u/5)*gr));
//установка цвета заливки стрелки
ms[number]. Item Image. Canvas. Brush. Colored White;
//отрисовка стрелки
ms[number]. Item Image.Canvas. Polygon(mas);
//радиус окружности в центре диаграммы Г2
Г2:=5;
//установка цвета заливки
ms[number]. Item Image. Canvas. Brush. Color:=background;
//отрисовка окружности в центре диаграммы
ms[number]. Item Image.Canvas. Ellipse(xi+xo-r2zyi+yo-
r2zXl+XO+r2zyi+yO+r2);
end;
148
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//уничтожение сервера
//скрытие главной формы
// вызов дополнительной формы
//выход из процедуры
//уничтожение сервера
//скрытие главной формы
// вызов дополнительной формы
//выход из процедуры
//добавление тегов в группу
//процедура, запускающая сервер и добавляющая в него
//сегмент и теги
procedure Run;
var
kinteger;
begin
try
//создание сервера
Server:=CreateComObject(ProglDToClasslD(Srv.Text)) as lOPCServer;
except // если не удалось создать сервер
//выводится сообщение об ошибке
ShowMessage('He могу запустить сервер!!!1);
Server:=nil;
MainForm.Hide;
AddForm.Show;
Exit;
end;
//добавление сегмента в сервер
HR:=ServerAddGroup(Server,Sgt.Text,true,500, о, Segment,
SegmentHandle);
if not Succeeded(HR) then //если произошла ошибка
begin
//показ сообщения об ошибке
ShowMessagefHe могу добавить сегмент!!!1);
Server:=nil;
MainForm.Hide;
AddForm.Show;
Exit;
end;
for i:=o to n-i do
begin
//полное имя тега
ms[i]. Item Name:=Sgt.Text+'.l+Node.Text+'.'+mas[i].Text;
//добавление тега
H R:=G rou p Add Ite m (Seg m e nt, m s[i]. Item N a m e,
SegmentHandle,VT_EM PTY,ms[i].Item Handle,ms[i].ltemType);
if not Succeeded(HR) then //если произошла ошибка
begin
//вывод сообщения об ошибке
ShowMessagefHe могу добавить тег l+ms[i].ltemName+l!!!');
Server:=niI; //уничтожение сервера
MainForm.Hide; //скрытие главной формы
149
РАЗРАБОТКА SCADA-СИСТЕМ
AddForm.Show; //вызов дополнительной формы
Exit; //выход из процедуры
end;
end;
MainForm.Timeri.Enabled:=true; //запуск таймера
end;
//процедура создания главной формы
procedure TMainForm.FormCreate(Sender: TObject);
var
i:integer; //счетчик цикла
j:integer; //переменная для временного хранения числа
f:TextFile; //файловая переменная
begin
background:=RGB(ioozi5Oz2oo); //установка цвета фона
//настройки главной формы
//заголовок формы
MainForm.Caption:='АПИ НГТУ, кафедра Автоматизации
Машиностроения. Круговые диаграммы со стрелкой1;
//установка стиля границ формы
Main Form. BorderStyl е:=bsSi ng le;
//установка разрешенных кнопок на главной форме
Main Form. Borderlcons:=[biSystem Menu, bi Minimize];
//установка цвета главной формы в цвет background
Main Form. Color:=background;
//абсцисса левого верхнего угла главной формы
MainForm. Left:=о;
//ордината левого верхнего угла главной формы
MainForm.Top:=o;
MainForm.Width:=Monitor.Width; //ширина главной формы
MainForm.Height:=Monitor.Height; //высота главной формы
//создание окна для вывода даты
Date:=TLabeledEdit.Create(Date); //создание компонента
Date.Parent:=MainForm; //установка родителя компонента
Date. Left:=5; //абсцисса левого верхнего угла компонента
Date.Тор:=20; //ордината левого верхнего угла компонента
Date.Height:=25; //высота компонента
Date.Font.Size:=i2; //размер шрифта компонента
Date.AutoSize:=false; //установка авторазмера компонента
150
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Date. EditLabel.Caption:='flATA:'; //заголовок компонента
Date.Width:=MainForm.Width div 8 -5; //ширина компонента
//установка свойства «только чтение» компонента
Date.ReadOnly:=True;
//цвет заголовка компонента
Date. EditLabel. Font. Colored White;
Date.Color:=background; //цвет компонента
//создание окна для вывода времени
Time:=TI_abeledEdit.Create(Date); //создание компонента
Time.Parent:=MainForm; //установка родителя компонента
//абсцисса левого верхнего угла компонента
Time.Left:=MainForm.Width div 8 +5;
Time.Top:=2O; //ордината левого верхнего угла компонента
Time.Height:=25; //высота компонента
Time.Font.Size:=i2; //размер шрифта компонента
Time.AutoSize:=false; //авторазмер компонента
Time.EditLabel.Caption:='ВРЕМЯ//заголовок компонента
Time.Width :=Main Form.Width div 8 -5; //ширина компонента
Time.ReadOnly:=True; //свойство «только чтение» компонента
Time.EditLabel.Font.Color:=clWhite; //цвет заголовка компонента
Time.Color:=background; //цвет компонента
//динамическое создание в цикле всех остальных компонентов
SetLength(mszn); //установка длины динамического массива
for i:=oto n-i do //создание элементов динамического массива
begin
//установка верхней и нижней границ измеряемой величины
ms[i].Up:=4; //установка верхней границы тега
ms[i].Down:=2; //установка нижней границы тега
//создание панели на главной форме
//создание компонента
ms[i].Panel:=TPanel.Create(ms[i]. Panel);
//установка родителя компонента
ms[i]. Panel. Parent:=Main Form;
//ширина компонента
ms[i].Panel.Width:=(MainForm.Width-10) div 4;
//высота компонента
ms[i].Panel.Height:=(MainForm.ClientHeight-Time.Height-30) div 2;
if i<=3 then
begin
151
РАЗРАБОТКА SCADA-СИСТЕМ
//абсцисса левого верхнего угла компонента
ms[i]. Panel. Left:=i*ms[i]. Panel. Width+2;
//ордината левого верхнего угла компонента
ms[i]. Panel.Top:=Time.Top+Time. Height+5;
end
else
begin
//абсцисса левого верхнего угла компонента
ms[i]. Panel. Left:=(i-4)*ms[i]. Panel.Width+2;
//ордината левого верхнего угла компонента
ms[i]. Panel.Top:=Time.Top+Time.Height+5+ms[i]. Panel. Height;
end;
ms[i]. Panel. Font.Size:=i2;
ms[i]. Panel. Bevel lnner:=bvRaised;
ms[i]. Panel. BevelOuter:=bvLowered;
ms[i]. Panel. Bevel Width :=2;
ms[i].Panel.Color:=background; //цвет компонента
//создание на панели окна вывода величины тега
//создание компонента
ms[i].ltmValue:=TEdit.Create(ms[i]. ItmValue);
ms[i].ItmValue.Parent:=ms[iJ.Panel; // родитель компонента
ms[i].ItmValue.AutoSize:=false; //авторазмер компонента
//ширина компонента
ms[i]. ItmValue.Width :=ms[i]. Panel.Width-20;
ms[i].ItmValue.Height:=25; // высота компонента
ms[i].ItmValue.Font.Size:=i2; // размер шрифта компонента
//абсцисса левого верхнего угла компонента
ms[i]. ItmValue. I_eft:=io;
//ордината левого верхнего угла компонента
ms[i].ltm Vai ue.Top:=ms[i]. Panel. Height-ms[i]. ItmValue. Height-io;
//свойство «только чтение» компонента
ms[i]. ItmValue. ReadOnly:=true;
ms[i].ItmValue.Color:=background; //цвет компонента
//создание на панели компонента для вывода графики
ms[i].ltemlmage:=Tlmage.Create(ms[i]. Item Image);
ms[i].Itemimage.Parent:=ms[iJ.Panel; //родитель компонента
//абсцисса левого верхнего угла компонента
ms[i]. Item Image. Left:=5;
//ордината левого верхнего угла компонента
ms[i].ltemlmage.Top:=5;
152
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//ширина компонента
ms[i]. Item lmage.Width:=ms[i]. Panel. Width-io;
//высота компонента
ms[i]. Item Image.Height:=ms[i]. Panel. Height-ms[i].ltmValue. Height-20;
ms[i]. Item Image.Canvas. Brush.Color:=background;
//отрисовка компонента
ms[i]. Item Image.Canvas. Fill Rect(Rect(ozozms[i]. Item Image.
Width,ms[i]. Item Image. Height));
ms[i]. Item Image. Canvas. Pen. Width :=i;
ms[i]. Item Image.Canvas. Pen.Colored White;
//размер шрифта компонента
ms[i]. Item Image.Canvas. Font.Size:=io;
ms[i]. Item Image.Canvas. Font.Colored White;
ms[i]. Item Image.Canvas.TextOut(5z5z'KAHAJl '+lntToStr(i+i));
//создание на панели движка установки нижней границы тега
ms[i]. Itm Down :=TTrackBar.Create(ms[i]. Itm Down);
ms[i].ltmDown.Parent:=ms[i].Panel; //родитель компонента
ms[i]. Itm Down.Orientation :=trHorizontal;
//ширина компонента
ms[i]. Itm Down.Width :=ms[i]. Item Image.Width;
//высота компонента
ms[i].ltmDown.Height:=ms[i].Itemimage.Height div 15;
//абсцисса левого верхнего угла компонента
ms[i]. Itm Down. Left:=5;
//ордината левого верхнего угла компонента
ms[i].ltmDown.Top:=ms[i]. Itemimage. Height-ms[i]. Itm Down. Height-10;
ms[i]. Itm Down. Frequency:=i;
ms[i].ltmDown.Min:=o;
m s[i]. Itm Down. M ax:=n n;
ms[i].ltmDown.ThumbLength:=io;
ms[i]. Itm Down. Position :=round(2/s);
ms[i]. Itm Down.Tag:=i;
//создание на панели движка установки верхней границы тега
//создание компонента
ms[i].ltmUp:=TTrackBar.Create(ms[i].ltmUp);
ms[i].ltmUp.Parent:=ms[i].Panel; //родитель компонента
ms[i]. Itm Up. Orientation :=trHorizontal;
//ширина компонента
ms[i]. Itm Up.Width :=ms[i]. Item Image.Width;
//высота компонента
ms[i].ltmUp.Height:=ms[i].Item Image.Height div 15;
153
РАЗРАБОТКА SCADA-СИСТЕМ
//абсцисса левого верхнего угла компонента
ms[i].ltmUp.Left:=5;
//ордината левого верхнего угла компонента
ms[i].ltmUp.Top:=ms[i].ltmDown.Top-ms[i].ltmUp. Height-30;
ms[i].ltmUp.Frequency:=i;
ms[i].ltmUp.Min:=o;
ms[i].ltmUp.Max:=nn;
ms[i].ltmUp.ThumbLength:=io;
ms[i]. Itm Up. Position :=round(4/s);
ms[i].ltmUp.Tag:=i+io;
//определение процедуры, обрабатывающей события на всех
//движках
ms[i]. Itm Down. OnChange:=Tracl<BarChange;
ms[i].ltmUp.OnChange:=Tracl<BarChange;
end;
//создание кнопки AddFormRun перехода на форму AddForm
// с изображением гаечного ключа
Add Form Run :=TSpeed Button. Create(Add Form Run);
AddFormRun.Parent:=MainForm; //родитель компонента
Add Form Run.Width :=25; //ширина компонента
AddFormRun.Height:=25; //высота компонента
//абсцисса левого верхнего угла компонента
Add Form Run. Left:=Time. Left+Time.Width+5;
//ордината левого верхнего угла компонента
Add Form Run.Тор:=2О;
Add Form Run. Flat:=true;
Add Form Run.Glyph. Load From File('Key. bmp');
Add Form Run.OnClick:=Add Form RunClick;
Add Form Run.ShowHint:=true;
Add Form Run. Hint:='HacTpoMKn сервера1;
//создание логотипа
Logo:=Tlmage.Create(Logo);
Logo.Parent:=MainForm; //родитель компонента
Logo.Width:=ioi; //ширина компонента
Logo.Height:=5i; //высота компонента
//абсцисса левого верхнего угла компонента
Logo. Left:=Main Form.Width-Logo.Width-15;
//ордината левого верхнего угла компонента
Logo.Top:=2;
Logo. Picture. Load From File( AM. bmp');
154
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//чтение положений ползунков движков граничных значений
//из файла AutoSave.sav и занесение этих значений в массив ms
if FileExists('AutoSave.sav') then
begin
AssignFile(f, AutoSave.sav1);
Reset(f);
for i:=o to 10 do
readln(f);
for i:=o to n-i do
begin
readln(fj);
ms[i].ltm Up. Position :=j;
ms[i].Up:=j*s;
readln(fj);
ms[i].ltm Down. Position :=j;
ms[i].Down:=j*s;
end;
CloseFile(f);
end;
end;
//действия, выполняемые при закрытии формы
procedure TMainForm. FormClose(Sender: TObject; var Action:
TCIoseAction);
var
f:TextFile;
i:integer;
inf:Word;
begin
inf:=MessageDlg('Bbi уверены?1, mtlnformation/[mbYes/mbNo]/o);
if inf=mrYes then
begin
//запись в файл AutoSave.sav имен ОРС-сервера, сегмента,
//узла, тегов, чтение положений ползунков движков граничных
//значений и запись их в файл AutoSave.sav
Assign File(f, AutoSave.sav1);
Rewrite(f);
writeln(f,Srv.Text);
writeln(f,Sgt.Text);
writeln(f,Node.Text);
for i:=o to n-i do
writeln(f,mas[i].Text);
for i:=o to n-i do
155
РАЗРАБОТКА SCADA-СИСТЕМ
begin
writeln(fzms[i].ltm Up. Position);
writeln(fzms[i].ltm Down. Position);
end;
CloseFile(f);
Timeri.Enabled:=false;
Server:=nil;
SetLength(mszo);
Action:=caFree;
Application.Terminate;
end
else
Action:=caNone;
end;
//действия no поступлению очередного сигнала таймера
procedure TMainForm J-imeriTimer(Sender: TObject);
var
i:integer;
dt:TDateTime;
begin
dt:=Now;
Date.Text:=FormatDateTime('dd.MM.yyyy r.'zdt);
Time.Text^FormatDateTimeChhimmiss'/dt);
//чтение значений тегов из OPC-сервера
for i:=o to n-i do
begin
//чтение из сегмента Segment значения и качества связи тега
//с хэндлом
// Item Handle в переменные ItemValue и ItemQuality
HR:=ReadOPCGroupltemValue(Segmentzms[i].ltemHandlezms[i].
Item Value, ms[i]. ItemQuality);
if Succeeded(HR) then // если прочитали без ошибок
begin
if GetltemType(ms[i].ltemValue)='Float' then
begin
//если измеряемая величина станет меньше ofooi
if StrToFloat(ms[i].ltemValue)<o.ooi then
mstn.ltemValue^'o1; //установка ItemValue в ноль
//округление измеряемой величины
ms[i].ltmValue.Text:=FloatToStrF(StrToFloat(ms[i].ltemValue)zfffixedz5z3);
// вызов процедуры рисования диаграммы i+i канала
156
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Diagramma(StrToFloat(ms[i].ltemValue)zi);
end;
if GetltemType(ms[i].ltemValue)='lntegerl then
// вызов процедуры рисования диаграммы i+i канала
Diagramma(StrTolnt(ms[i].ltemValue)zi);
//присвоение ItemValue округленной величины
ms[i]. Item Vai ue:=ms[i]. Itm Value.Text;
end;
end;
end;
//процедура перехода от MainForm кAddForm, вызываемая
//щелчком на кнопке с изображением гаечного ключа
procedure TMainForm.AddFormRunClick(Sender: TObject);
begin
MainForm.Hide;
Timeri. Enabled :=false;
Server:=nil;
AddForm.Show;
end;
//процедура, вызываемая, когда ползунок одного из
//16 движков установки верхней или нижней границы тега
// был сдвинут с помощью мыши
procedure TMainForm.TrackBarChange(Sender: TObject);
var
trbar:TTrackBar;
begin
trbar:=Sender asTTrackBar;
if trbar.Tag<=7 then
begin
// если был сдвинут ползунок движка установки нижней границы
if ms[trbar.Tag]. Itm Down. Position>=ms[trbar.Tag]. Itm Up. Position
then
trbar. Position :=ms[trbar.Tag]. Itm Up. Position;
ms[trbar.Tag].Down:=trbar. Position's;
end
else
begin
// если был сдвинут ползунок движка установки верхней
//границы
if ms[trbar.Tag-io].ltmUp.Position<=ms[trbar.Tag-io].ltmDown.
Position then
157
РАЗРАБОТКА SCADA-СИСТЕМ
trbar. Position:=ms[trbar.Tag-io]. ItmDown. Position;
ms[trbar.Tag-io].Up:=trbar.Position*s;
end
end;
//процедура, возникающая при уничтожении MainForm
procedure TMainForm.FormDestroy(Sender: TObject);
begin
Server:=nil; //уничтожение сервера
SetLength(mszo);
end;
end.
2.5. Просмотрщик тегов в виде круговой диаграммы
Содержимое папки, в которой находятся файлы проекта «Кру-
говая диаграмма», приведено на рис. 2.17. Для работы приложе-
ния, как и в предыдущих главах, использованы две формы:
1. AddForm — дополнительная форма;
2. MainForm — основная форма.
Рис. 2.17. Папка проекта «Круговая диаграмма»
158
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Дополнительная форма AddForm (рис. 2.18) предназначена
для:
- ввода имен сервера, сегмента, узла, восьми тегов;
- перехода к основной форме MainForm с помощью кнопки
ОК;
- выполнения настроек Fastwel PlcNet ОРС-сервера путем
перехода к нему с помощью кнопки «Сервер».
Внешний вид и работа формы AddForm аналогичны рассмо-
тренным в предыдущем разделе.
Рис. 2.18. Дополнительная форма AddForm проекта «Круговая диаграмма»
Основная форма MainForm (рис. 2.19) предназначена для:
- вывода в соответствующие окна даты и времени;
- вывода на экран логотипа;
- вывода на экран восьми панелей, на каждой из которых рас-
положены графические изображения диаграмм величин со-
ответствующих тегов, а также два движка установки верх-
ней и нижней границ величины тега;
- вывода величины тега в числовом виде;
- вывода статуса тега;
- вывода индикатора уровня величины тега;
- закрытия приложения;
- перехода к дополнительной форме AddForm.
159
РАЗРАБОТКА SCADA-СИСТЕМ
Рис. 2.19. Основная форма MainForm
На рис. 2.20 обозначены все компоненты формы MainForm,
а также элементы, выводимые в графической форме на поверхность
формы.
Содержимое файла Autosave.sav, предназначенного для хране-
ния в текстовом виде имен ОРС-сервера, сегмента сети, узла сети,
имен тегов, а также настроек верхней и нижней границ для всех
восьми тегов, точно такое же, что и в двух предыдущих разделах.
Работа формы MainForm, ее компонентов и графических эле-
ментов описывается в модуле Main.
Состав и назначение процедур и функций модуля Main точно
такие же, что и в приложениях, рассмотренных ранее. Единствен-
ное существенное отличие этого модуля от других — процедура
Diagramma (u:real; number:integer), которая выполняет отрисовку
круговой диаграммы для тега, имя которого занесено в канал с но-
мером number + 1 (рис. 2.18). Величина тега определяется параме-
тром и.
160
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Величине тега и соответствует определенное число j полно-
стью закрашенных элементов в диаграмме. Однако может оказаться
так, что (j+l)-n элемент должен быть закрашен не полностью. Для
графической отрисовки такого не полностью закрашенного элемен-
та используется переменная р — процент размера закрашенной ча-
сти 0+1)-го элемента от размера этого элемента.
Рис. 2.20. Компоненты формы MainForm и элементы,
представленные на ней в графическом виде
Основой круговой диаграммы является окружность, вписанная
в прямоугольник с координатами углов xl, у1 и х2, у2 (рис. 2.21).
Окружность и прямоугольник — это графические фигуры, располо-
женные на компоненте Item-Image, предназначенном для вывода на
его поверхность Canvas графических построений. В свою очередь,
компонент Itemimage занимает часть поверхности панели Panel.
Панель предназначена для объединения всех компонентов и графи-
ческих элементов, относящихся к одному каналу (тегу).
161
РАЗРАБОТКА SCADA-СИСТЕМ
Окружность имеет радиусы хО и уО по осям X и Y соответ-
ственно, величины которых в нашем случае совпадают.
При реализации процедуры выполняются следующие дей-
ствия. Вначале определяется цвет, которым будут закрашиваться j
закрашенных элементов шкалы диаграммы, индикатор уровня тега
и строка статуса тега, помещенная в центр круга. Одновременно
с этим определяется, какой статус («ниже нормы», «норма», «выше
нормы») будет выведен в центр диаграммы.
Для выполнения всех этих действий величина и тега сравни-
вается с величинами ms [number] .Up и ms [number] .Down, полу-
ченными соответственно с движков установки верхней и нижней
границ изменения величины тега.
Затем выполняется отрисовка индикатора уровня тега цветом,
который был определен ранее. Далее выполняются вычисления ко-
ординат xl, yl, х2, у2 и радиусов хО, уО (рис. 2.21).
Рис. 2.21. Построение круговой диаграммы
Теперь обратимся к механизму формирования элементов шка-
лы диаграммы (их 20). Таких элементов в составе графических
162
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
примитивов Delphi нет. Поэтому предлагается следующее решение
(рис. 2.22):
- отрисовать nn (пп = 20) секторов с радиусом хО, в совокуп-
ности образующих круг; j из этих секторов должны быть
закрашены цветом (желтым, зеленым, красным), определяе-
мым ранее; остальные (nn - j) секторов должны быть окра-
шены в цвет фона;
- в центре полученной фигуры расположить круг с радиусом
rl с закраской цветом фона, который можно представить
как совокупность пп малых (внутренних) секторов
с радиусом rl.
Рассмотрим эти процессы более подробно.
Угловой размер ugl сектора определяется по формуле:
ugl = 360° / nn = 360° 120 = 18°.
Для отрисовки закрашенного сектора в Delphi имеется графи-
ческая процедура Pie (xl, yl, х2, у2, хЗ, уЗ, х4, у4). Здесь хЗ, уЗ и х4,
у4 — координаты начала и конца дуги сектора (рис. 2.22).
Маленький, внутренний Большой, внешний
Рис. 2.22. Формирование элементов шкалы диаграммы
163
РАЗРАБОТКА SCADA-СИСТЕМ
После отрисовки j закрашенных секторов аналогичным обра-
зом отрисовываются (nn - j) незакрашенных секторов (закрашен-
ных цветом фона). Затем выполняются действия по закрашиванию
одного не полностью закрашенного j+1 сектора, как это показано на
рис. 2.23. Закрашенной части последнего не полностью закрашен-
ного сектора соответствует величина:
UU = U - j X S.
Здесь:
и — величина тега;
j х s — часть величины тега, которая убралась в j закрашенных
секторах.
s — цена одного деления шкалы диаграммы
(s = 5 В / nn = 5 В / 20 = 0,25 В).
Рис. 2.23. Отрисовка не полностью закрашенного элемента
Вычисляются координаты хЗ, уЗ, х4, у4 начала и конца дуги
этого сектора, и он закрашивается с помощью процедуры Pie.
164
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Далее идет отрисовка внутреннего круга, представляющего со-
вокупность всех nn внутренних малых секторов.
Выполняется отрисовка цифр от 0 до 5 на движках измене-
ния верхней и нижней границ тега, рисок на круговой диаграмме и
оцифровка шкалы диаграммы. В конце процедуры в центр диаграм-
мы выводится статус (состояние) тега. Программный код процеду-
ры Main с необходимыми комментариями приведен в листинге 2.5.
Листинг 2.5
unit Main;
interface
uses
Windows, Messages, Syslltils, Variants, Classes, Graphics,
Controls, Forms,
Dialogs, OPCDA, OPCTypes, OPCUtils, ExtCtrls, StdCtrls, ComObj,
ActiveX, ComCtrls, Addllnit, Buttons, DB, DBCIient, MConnect,
SConnect;
type
TMainForm = class(TForm)
TimernTTimer; //таймер
//действия, выполняемые при создании формы
procedure FormCreate(Sender: TObject);
//действия, выполняемые при закрытии формы
procedure FormClose(Sender: TObject; var Action: TCIoseAction);
//действия, выполняемые при поступлении очередного сигнала
//с таймера
procedure TimenTimer(Sender: TObject);
//реакция на изменение положения ползунка движков изменения
//верхней или нижней границы величины тега
procedure TrackBarChange(Sender: TObject);
//действия по нажатию кнопки AddFormRun с гаечным ключом
//перехода к форме AddForm
procedure AddFormRunClick(Sender: TObject);
//действия no уничтожению формы
procedure FormDestroy(Sender: TObject);
private
{Private declarations}
public
{Public declarations}
end;
165
РАЗРАБОТКА SCADA-СИСТЕМ
const
//число тегов
п=8;
// число элементов в шкале диаграммы
пп=2О;
//цена деления шкалы
3=0.25;
type
// тег
Т Ite record
// имя тега
ltemName:string;
//хэндл тега
ltemHandle:OPCHANDLE;
//тип тега
ItemTypeiTVarType;
//величина тега
ltemValue:string;
//качество связи тега
ItemQualityiword;
//компонент для рисования
ltemlmage:Tlmage;
//окно вывода величины тега
ItmVal ue:TEdit;
// движок для изменения нижней границы тега
ItmDowmTTrackBar;
// движок для изменения верхней границы тега
ltmUp:TTrackBar;
//компонент для объединения компонентов в группу
PanekTPanel;
//верхняя граница тега
Up:real;
//нижняя граница тега
Dowmreal;
end;
function GetltemType(ltemValue:string):string;
procedure Run;
procedure Diagramma(u:real;number:integer);
var
//цвет фона
background:TColor;
166
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//главная форма
MainForm: TMainForm;
//динамический массив тегов
ms:array ofTItem;
//переменная, хранящая результат операции с тегом
// в сегмент
Segment: lOPCItemMgt;
//хэндл сегмента
SegmentHandle:OPCHANDLE;
//окна вывода времени и даты
Date/Time:TLabeledEdit;
//кнопка с гаечным ключом вызова настройки сервера
Add Form Run :TSpeed Button;
//логотип
Logo:Tlmage;
//интерфейс, осуществляющий добавление и удаление
//сегментов в ОРС-сервер
ServerdOPCServer;
implementation
{$R *.dfm}
//функция, возвращающая тип тега
function GetltemType(ltemValue:string):string;
var
i,s:byte;
begin
Result:='Timer';
if (UpperCase(ltemValue)='TRUEl) or (UpperCase(ltemValue)='FALSEl)
then
begin
Result:='Boolean';
exit;
end;
for i:=i to Length(ltemValue) do
if (ItemVaIue[i]='.') or (ItemValuefiJ^1,1) then
begin
Result:='Float';
exit;
end;
s:=o;
for i:=i to Length(ltemValue) do
167
РАЗРАБОТКА SCADA-СИСТЕМ
if ItemVaIue[i] in [lol/lil/l2l/l3l/lzhl/l5l/l6l/l7l/l8l/l9l/l-l/l+l] then
inc(s);
if s=l_ength(ltemValue) then
begin
Result:='lnteger';
exit;
end;
end;
//процедура, выполняющая создание сервера, добавление
// в него сегмента и тегов в сегмент
procedure Run;
var
i:integer;
begin
try
//создание сервера
Server:=CreateComObject(ProglDToClasslD(Srv.Text)) as lOPCServer;
// если не смогли создать сервер
except
//показ сообщения об ошибке
ShowMessage('He могу запустить сервер!!!1);
//уничтожение сервера
Server:=nil;
//скрытие главной формы
MainForm.Hide;
// вызов дополнительной формы
AddForm.Show;
//выход из процедуры
Exit;
end;
//добавление сегмента в сервер
R:=ServerAddGroup(Server/Sgt.Text/true/5OO/o/Segment/SegmentHandle);
// если произошла ошибка
if not Succeeded(HR) then
begin
//показ сообщения об ошибке
ShowMessagefHe могу добавить сегмент!!!1);
//уничтожение сервера
Server:=nil;
168
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//скрытие главной формы
MainForm.Hide;
//вызов дополнительной формы
AddForm.Show;
//выход из процедуры
Exit;
end;
//добавление тегов в сегмент
for i:=o to n-i do
begin
//полное имя тега
ms[i]. Item Name:=Sgt.Text+'.l+Node.Text+'.'+mas[i].Text;
//добавление тега
HR:=GroupAddltem(Segmentzms[i].ltemNamezSegmentHandlez
VT_EM PTY, ms[i]. Item Handle, ms[i].ltemType);
// если произошла ошибка
if not Succeeded(HR) then
begin
//показ сообщения об ошибке
ShowMessagefHe могу добавить переменную l+ms[i].ltemName+l!!!');
//уничтожение сервера
Server:=nil;
//скрытие главной формы
MainForm.Hide;
// вызов дополнительной формы
AddForm.Show;
//выход из процедуры
Exit;
end;
end;
//запуск таймера
Main Form .Timen. Enabled :=true;
end;
//создание формы, панелей, окон, движков
procedure TMainForm.FormCreate(Sender: TObject);
var
//счетчик цикла
i:integer;
//переменная для временного хранения числа
j:integer;
169
РАЗРАБОТКА SCADA-СИСТЕМ
//файловая переменная
f:TextFile;
begin
//установка цвета фона
background:=RGB(ioozi5Oz2oo);
// заголовок главной формы
MainForm.Саption:='АПИ НГТУ, кафедра Автоматизации
Машиностроения. Круговые диаграммы1;
//установка стиля границ главной формы
Main Form. BorderStyle:=bsSingle;
//установка разрешенных кнопок на главной форме
Main Form. Borderlcons:=[biSystem Menu, biMinimize];
//установка цвета главной формы в цвет background
Main Form. Color:=background;
//установка абсциссы левого верхнего угла главной формы
М ain Form. Left:=о;
//установка ординаты левого верхнего угла главной формы
MainForm.Top:=o;
//установка ширины главной формы
Main Form .Width :=Monitor.Width;
//установка высоты главной формы
Main Form. Height:=Monitor. Height;
//создание окна для вывода даты
//создание компонента
Date:=TLabeledEdit.Create(Date);
//установка родителя компонента
Date. Parent:=Main Form;
//установка абсциссы левого верхнего угла компонента
Date. Left:=5;
//установка ординаты левого верхнего угла компонента
Date.Top:=2O;
//установка высоты компонента
Date.Height:=25;
//установка размера шрифта компонента
Date.Font.Size:=i2;
//установка авторазмера компонента
Date.AutoSize:=false;
//установка заголовка компонента
Date. EditLabel.Caption :='ДАТА:';
//установка ширины компонента
Date.Width:=MainForm.Width div 8 -5;
170
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//установка свойства «только чтение» компонента
Date.ReadOnly:=True;
//установка цвета заголовка компонента
Date. EditLabel. Font.Color:=cl White;
//установка цвета компонента
Date.Color:=background;
//создание окна для вывода времени
//создание компонента
Time:=TLabeledEdit.Create(Date);
//установка родителя компонента
Time.Parent:=MainForm;
//установка абсциссы левого верхнего угла компонента
Time.Left:=MainForm.Width div 8 +5;
//установка ординаты левого верхнего угла компонента
Time.Top:=2O;
//установка высоты компонента
Time.Height:=25;
//установка размера шрифта компонента
Time.Font.Size:=i2;
//установка авторазмера компонента
Time.AutoSize:=false;
//установка заголовка компонента
Time. EditLabel.Caption :='ВРЕМЯ:';
//установка ширины компонента
Time.Width :=Main Form.Width div 8 -5;
//установка свойства «только чтение» компонента
Time.ReadOnly:=True;
//установка цвета заголовка компонента
Time. EditLabel. Font.Colored White;
//установка цвета компонента
Time.Color:=background;
//определение длины динамического массива
SetLength(mszn);
//создание элементов динамического массива
for i:=o to n-i do
begin
//установка верхней границы величины i-го тега
ms[i].Up:=4;
//установка нижней границы величины i-го тега
ms[i].Down:=2;
171
РАЗРАБОТКА SCADA-СИСТЕМ
//создание панели на главной форме для i-го тега
//создание компонента
ms[i]. Panel :=TPanel.Create(ms[iJ. Panel);
//установка родителя компонента
ms[i]. Panel. Parent:=Main Form;
//установка ширины компонента
ms[i].Panel.Width:=(MainForm.Width-io) div 4;
//установка высоты компонента
ms[i]. Panel. Height:=(Main Form.ClientHeight-Time. Height-30) div 2;
if i<=3 then
begin // четыре верхних панели
//установка абсциссы левого верхнего угла компонента
ms[i]. Panel. Left:=i*ms[i]. Panel. Width+2;
//установка ординаты левого верхнего угла компонента
ms[i]. Panel.Top:=Time.Top+Time. Height+5;
end
else
begin // четыре нижних панели
//установка абсциссы левого верхнего угла компонента
ms[i]. Panel. Left:=(i-4)*ms[i]. Panel.Width+2;
//установка ординаты левого верхнего угла компонента
ms[i]. Panel.Top:=Time.Top+Time. Height+5+ms[i]. Panel. Height;
end;
//установка размера шрифта компонента
ms[i]. Panel. Font.Size:=i2;
//установка стиля внутренней границы компонента
ms[i]. Panel. Bevel lnner:=bvRaised;
//установка стиля внешней границы компонента
ms[i]. Panel. BevelOuter:=bvLowered;
//установка толщины границы компонента
ms[i]. Panel. Bevel Width :=2;
//установка цвета компонента
ms[i]. Panel. Color:=background;
//создание окна вывода величины тега
ms[i].ltmValue:=TEdit.Create(ms[i].ltmValue);
//установка родителя компонента
ms[i].ltmValue.Parent:=ms[i]. Panel;
//установка авторазмера компонента
ms[i].ltmValue.AutoSize:=false;
//установка ширины компонента
ms[i]. ItmVal ие.Width :=ms[i]. Panel.Width-20;
172
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//установка высоты компонента
ms[i]. ItmValue. Height:=25;
//установка размера шрифта компонента
ms[i]. ItmValue. Font.Size:=i2;
//установка абсциссы левого верхнего угла компонента
ms[i]. ItmValue. I_eft:=io;
//установка ординаты левого верхнего угла компонента
ms[i].ltm Vai ue.Top:=ms[i]. Panel. Height-ms[i]. ItmValue. Height-io;
//установка свойства «только чтение» компонента
ms[i]. ItmValue. ReadOnly:=true;
//установка цвета компонента
ms[i]. ItmValue.Color:=background;
//создание компонента, на котором будет рисоваться
//диаграмма
ms[i]. Item lmage:=Tlmage.Create(ms[i]. Item Image);
//установка родителя компонента
ms[i]. Item Image. Parent:=ms[i]. Panel;
//установка абсциссы левого верхнего угла компонента
ms[i]. Item Image. Left:=5;
//установка ординаты левого верхнего угла компонента
ms[i].ltemlmage.Top:=5;
//установка ширины компонента
ms[i]. Item Image.Width :=ms[i]. Panel.Width-io;
//установка высоты компонента
ms[i].Itemimage.Height:=ms[i]. Panel. Height-ms[i]. ItmValue.Height-20;
//установка цвета заливки компонента
ms[i]. Item Image.Canvas. Brush.Color:=background;
//отрисовка закрашенного прямоугольника
ms[i]. Item Image.Canvas. Fill Rect(Rect(ozozms[i]. Item Image.
Width,ms[i]. Item Image. Height));
//установка ширины линии
ms[i]. Item Image. Canvas. Pen. Width =2;
//установка цвета линии
ms[i]. Item Image.Canvas. Pen.Colored White;
//установка размера шрифта компонента
ms[i]. Item Image.Canvas. Font.Size:=io;
//установка цвета шрифта компонента
ms[i]. Item Image.Canvas. Font.Colored White;
//вывод надписи
ms[i]. Item Image.Canvas.TextOut(5z5z'KAHAJl '+lntToStr(i+i));
173
РАЗРАБОТКА SCADA-СИСТЕМ
//создание движка установки нижней границы тега
ms[i]. Itm Down :=TTrackBar.Create(ms[i]. Itm Down);
//установка родителя компонента
ms[i]. Itm Down. Parent:=ms[iJ. Panel;
//установка типа ориентации компонента
ms[i]. Itm Down.Orientation :=trHorizontal;
//установка ширины компонента
ms[i]. Itm Down.Width :=ms[i]. Item Image.Width;
//установка высоты компонента
ms[i].ltmDown.Height:=ms[i].Itemimage.Height div 15;
//установка абсциссы левого верхнего угла компонента
ms[i]. Itm Down. Left:=5;
//установка ординаты левого верхнего угла компонента
ms[i].ltmDown.Top:=ms[i]. Itemimage. Height-ms[i].ltmDown. Height-10;
//установка цены деления компонента
ms[i]. Itm Down. Frequency:=i;
//установка минимального значения шкалы компонента
ms[i]. Itm Down. Min :=o;
//установка максимального значения шкалы компонента
ms[i]. Itm Down. Max:=nn;
//установка толщины шкалы движка
ms[i].ltmDown.ThumbLength:=io;
//установка позиции ползунка компонента
ms[i]. Itm Down. Position :=round(2/s);
//установка идентификационного номера компонента
ms[i]. Itm Down. Tag:=i;
//создание движка установки верхней границы тега
ms[i].ltmUp:=TTracl<Bar.Create(ms[i].ltmUp);
//установка родителя компонента
ms[i]. Itm Up. Parent:=ms[i]. Panel;
//установка типа ориентации компонента
ms[i]. Itm Up. Orientation :=trHorizontal;
//установка ширины компонента
ms[i]. Itm Up.Width :=ms[i]. Item Image.Width;
//установка высоты компонента
ms[i].ltmUp.Height:=ms[i]. Item Image. Height div 15;
//установка абсциссы левого верхнего угла компонента
ms[i]. Itm U р. Left:=5;
//установка ординаты левого верхнего угла компонента
ms[i]. Itm Up.Top:=ms[i]. Itm Down. Top-ms[i]. Itm Up. Height-30;
//установка цены деления компонента
174
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
ms[i].ltmUp.Frequency:=i;
//установка минимального значения шкалы компонента
ms[i].ltmUp.Min:=o;
//установка максимального значения шкалы компонента
ms[i].ltmUp.Max:=nn;
//установка толщины шкалы движка
ms[i].ltmUp.ThumbLength:=io;
//установка позиции ползунка
ms[i].ltmUp.Position:=round(4/s);
//установка идентификационного номера компонента
ms[i].ltmUp.Tag:=i+io;
//определение процедуры OnChange движков
ms[i]. Itm Down. OnChange:=Tracl<BarChange;
ms[i].ltmUp.OnChange:=Tracl<BarChange;
end;
//создание кнопки перехода к форме AddForm
Add Form Run :=TSpeed Button.Create(Add Form Run);
//установка родителя компонента
Add Form Run. Parent:=Main Form;
//установка ширины компонента
Add Form Run.Width :=25;
//установка высоты компонента
Add Form Run. Height:=25;
//установка абсциссы левого верхнего угла компонента
Add Form Run. Left:=Time.Left+Time.Width+5;
//установка ординаты левого верхнего угла компонента
Add Form Run.Тор:=2О;
//установка прозрачности компонента
Add Form Run. Flat:=true;
//загрузка картинки из файла
Add Form Run.Glyph. Load From File('Key. bmp1);
//установка свойства показ подсказки
Add Form Run.ShowHint:=true;
//установка свойства подсказка
Add Form Run. Hint:='HacTpoMKM сервера1;
//определение процедуры компонента
Add Form Run.OnClick:=Add Form RunClick;
//создание логотипа
Logo:=Tlmage.Create(Logo);
175
РАЗРАБОТКА SCADA-СИСТЕМ
//установка родителя компонента
Logo.Parent:=MainForm;
//установка ширины компонента
Logo.Width:=ioi;
//установка высоты компонента
l_ogo.Height:=5i;
//установка абсциссы левого верхнего угла компонента
Logo. Left:=Main Form.Width-Logo.Width-15;
//установка ординаты левого верхнего угла компонента
Logo.Top:=2;
//загрузка картинки из файла
Logo. Picture. Load From FileCAM.bmp1);
//поиск файла AutoSave.sav и чтение хранящихся в нем верхних
//и нижних границ тега
//поиск файла AutoSave.sav в текущем каталоге
if FileExists('AutoSave.sav') then
begin
// связь файловой переменной с файлом
AssignFile(f, AutoSave, sav1);
//открытие файла для чтения
Reset(f);
//пропуск 11 строк в файле
for i:=o to 10 do
//пропуск одной строки в файле
readln(f);
//чтение из файла нижней и верхней границ всех тегов
for i:=o to n-i do
begin
//чтение верхней границы i-го тега
readln(fj);
//установка ползунка движка в позицию j
ms[i]. Itm Up. Position :=j;
//установка верхней границы i-го тега
ms[i].Up:=j*s;
//чтение нижней границы i-го тега
readln(fj);
//установка ползунка движка в позицию j
ms[i].ltm Down. Position :=j;
//установка нижней границы i-го тега
ms[i].Down:=j*s;
176
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
end;
// закрытие файла
CloseFile(f);
end;
end;
//процедура, выполняющая действия при закрытии формы
procedure TMainForm.FormClose(Sender: TObject; var Action:
mTCIoseAction);
var
//файловая переменная
f:TextFile;
//счетчик цикла
i:integer;
//переменная для хранения выбранного действия пользователя
inf:Word;
begin
//вызов диалогового окна для закрытия формы
inf:=MessageDlg('Вы уверены?1,mtlnformation/[mbYes/mbNo]/o);
//если нажата кнопка Yes, то запись в файл AutoSave.sav
//текущих настроек сервера, верхних и нижних границ всех тегов
if inf=mrYes then
begin
//связь файловой переменной с файлом
AssignFile(f,'AutoSave.sav1);
//перезапись файла
Rewrite(f);
//запись имени сервера
writeln(f,Srv.Text);
//запись имени сегмента
writeln(f,Sgt.Text);
//запись имени узла
writeln(f,Node.Text);
//запись имен и положений ползунков движков верхних и нижних
//границ для всех тегов
for i:=o to n-i do
//запись имени i-го тега
writeln(f,mas[i].Text);
//запись верхней и нижней границ i-го тега
for i:=o to n-i do
begin
177
РАЗРАБОТКА SCADA-СИСТЕМ
//запись верхней границы i-го тега
writeln(fzms[i]. Itm Up. Position);
//запись нижней границы i-го тега
writeln(fzms[i]. Itm Down. Position);
end;
//закрытие файла
CloseFile(f);
//отключение таймера
Timen. Enabled :=false;
//уничтожение сервера
Server:=nil;
//установка длины динамического массива в ноль
SetLength(mszo);
//разрешение на закрытие главной формы
Action:=caFree;
//закрытие приложения
Application.Terminate;
end
else
//отмена закрытия главной формы
Action:=caNone;
end;
//чтение переменных, а также даты и времени с сервера
procedure TMain Form .TimenTimer(Sender: TObject);
var
//счетчик цикла
i:integer;
//переменная, хранящая дату и время
dt:TDateTime;
begin
//чтение даты и времени
dt:=Now;
//запись в Date.text текущей даты
Date.Text:=FormatDateTime('dd.MM.yyyy r.'zdt);
//запись в Time.text текущего времени
TimeText^FormatDateTimeChhimmiss'/dt);
//чтение значений тегов из ОРС-сервера (i — номер канала);
//за каждым тегом закреплен свой канал, определяемый
//при работе с формой AddForm
for i:=o to n-i do
begin
178
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
// чтение из сегмента Segment значения и качества связи тега с
хэндлом ItemHandle в переменные ItemValue и ItemQuality
HR:=ReadOPCGroupltem Vai ue(Segmentzms[i]. Item Handle,ms[i].
Item Value, ms[i]. ItemQuality);
// если прочитали без ошибок
if Succeeded(HR) then
begin
// если тип переменной Float
if GetltemType(ms[i].ltemValue)='Floatl then
begin
// если величина переменной меньше o.ooi
if StrToFloat(ms[i].ltemValue)<o.ooi then
//установка ItemValue в нуль
msljJ.ltemValuei^o1;
//округление измеряемой величины
ms[i].ltmValue.Text:=FloatToStrF(StrToFloat(ms[i]. ItemValue),fffixed,5,з);
// вызов процедуры рисования диаграммы i+i канала
Diagramma(StrToFloat(ms[i]. Item Vai ue),i);
end;
//если тип переменной Integer
if GetltemType(ms[i].ltemValue)='lntegerl then
// вызов процедуры рисования диаграммы i+i канала
Diagramma(StrTolnt(ms[i]. ItemValue),i);
//присвоение ItemValue округленной величины
ms[i]. Item Vai ue:=ms[i].ltmValue.Text;
end;
end;
end;
//рисует диаграмму для канала с номером number+i
procedure Diagramma(u:real;number:integer);
const
//градус в радианах
gr=pi/i8o;
var
//счетчик
i integer;
//число закрашенных элементов в шкале диаграммы
j:integer;
//число градусов в одном элементе
ugkinteger;
179
РАЗРАБОТКА SCADA-СИСТЕМ
//радиус малого (внутреннего) сектора
ruinteger;
//ширина диаграммы
r2:integer;
//процент размера закрашенной части элемента от размера
//всего элемента в шкале диаграммы
pdnteger;
//цвет индикатора тега
Color:TColor;
// координаты левого верхнего угла индикатора тега
// координаты левого верхнего угла прямоугольника, в который
//вписываетя диаграмма
xizyi:integer;
//координаты правого нижнего угла индикатора тега
//координаты правого нижнего угла прямоугольника,
//в который вписывается диаграмма
X2zy2:integer;
//координаты начальной точки сектора
хЗ/УЗ:т1едег;
//координаты конечной точки сектора
xz^yzpinteger;
//радиусы диаграммы по осям хиу(хо= уо)
xozyo:integer;
//переменные для отрисовка рисок на диаграмме
xzy:integer;
//переменная для вывода текста
ss:string;
//высота закрашенной части элемента в шкале диаграммы
uu:real;
begin
//установка цвета
Color:=background;
//если величина тега меньше нижней границы
if u<ms[number].Down then
begin
//окраска желтым цветом
Color:=clYellow;
//статус тега
ss-'НИЖЕ НОРМЫ1;
end;
if (u<ms[number].Up) and (u>=ms[number].Down) then
begin
180
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//окраска зеленым цветом
Color:=clGreen;
//статус тега
ss-'HOPMA1;
end;
if u>=ms[number].Up then
begin
//окраска красным цветом
Color:=dRed;
//статус тега
ss-'ВЫШЕ НОРМЫ1;
end;
//отрисовка индикатора уровня тега (прямоугольник)
//координата х верхнего левого угла
xi:=ms[number].ltemlmage.Width-6o;
// координата у верхнего левого угла
yi:=5;
// координата х нижнего правого угла
x2:=ms[number].ltemlmage.Width-5;
// координата у нижнего правого угла
У2-25;
//установка цвета заливки закрашенных элементов диаграммы
Ци индикатора уровня тега
ms[number]. Item Image. Canvas. Brush. Color:=Color;
//отрисовка индикатора уровня тега
ms[number].ltemlmage.Canvas.Rectangle(Rect(xizyizx2zy2));
//установка размера шрифта
ms[number]. Item Image.Canvas. Font.Size:=io;
IIустановка цвета шрифта
ms[number]. Item Image.Canvas. Font.Colored White;
//установка цвета линии
ms[number]. Item Image.Canvas. Pen.Colored White;
//отрисовка диаграммы
//координаты прямоугольника, в который будет вписываться
//диаграмма, и радиусы по осям хиу
// координата yi
yi-15;
// координата у2
y2:=ms[number].ltemlmage.Height-
i5-ms[number].ltmDown.Height-3O-ms[number]. Itm Up. Height-15-15;
181
РАЗРАБОТКА SCADA-СИСТЕМ
//радиус уо
yo:=(y2-yi) div 2;
//координата xi
xi:=(ms[number].Itemimage.Width-2*yo) div 2;
//координата X2
x2:=ms[number].ltemlmage.Width-xi;
// радиус xo
xo:=(x2-xi) div 2;
//угол ugl, соответствующий одному сектору диаграммы
ugl:=round(36o/nn);
//число закрашенных элементов диаграммы
j:=trunc(u/s);
//если есть хотя бы один закрашенный элемент
if joo then
//отрисовка закрашенных элементов в шкале диаграммы
for i:=i to j do
begin
//координата xj
x3:=xi+xo-round(xo*cos(i*ugl*gr));
// координата уз
y3:=yi+yo-round(yo*sin(i*ugl*gr));
//координата X4
x4:=xi+xo-round(xo*cos((i-i)*ugl*gr));
// координата у4
y4:=yi+yo-round(yo*sin((i-i)*ugl*gr));
//отрисовка одного закрашенного элемента в шкале
// диаграммы
ms[number].ltemlmage.Canvas.Rie(xi/yi/x2/y2/x3/y3/xzh/y4);
end;
//установка цвета заливки незакрашенных элементов
ms[number]. Item Image. Canvas. Brush. Color:=background;
//отрисовка незакрашенных элементов в шкале диаграммы
for i:=j+i to nn do
begin
// координата хз
x3:=xi+xo-round(xo*cos(i*ugl*gr));
//координата уз
y3:=yi+yo-round(yo*sin(i*ugl*gr));
//координата X4
x4:=xi+xo-round(xo*cos((i-i)*ugl*gr));
// координата у4
y4:=yi+yo-round(yo*sin((i-i)*ugl*gr));
182
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//отрисовка одного незакрашенного элемента в шкале измерения
ms[number].ltemlmage.Canvas.Pie(xi/yi/x2/y2/x3/y3/xzh/yzh);
end;
//вычисление п
ri:=xo-2O;
//вычисление Г2
Г2:=хо-Г1;
//вычисление ии (часть величины тега, которая отражается
//частью последнего закрашенного элемента шкалы диаграммы)
uu:=u-j*s;
//процент закраски последнего закрашенного элемента шкалы
//диаграммы
p:=trunc(uu*ioo/s);
//установка цвета заливки
ms[number]. Item Image. Canvas. Brush. Color:=Color;
//если закрашенная часть больше о,os
if ии>=о.О5 then
begin
//координаты последнего закрашенного элемента шкалы
//диаграммы
//координата xj
x3:=xi+xo^ound(xo*cos((j*ugl4d:runc(p*ugl/ioo))*gr));
// координата yj
y3:=yi+yo-round(yo*sin((j*ugl+trunc(p*ugl/ioo))*gr));
//координата Х4
x4:=xi+xo^ound(xo*cos(j*ugl*gr));
// координата у4
y4:=yi+yo-round(yo*sin(j*ugHgr));
//отрисовка последнего закрашенного элемента шкалы
//диаграммы
ms[number].ltemlmage.Canvas.Pie(xi/yi/x2/y2/x3/y3/xzh/yzh);
end;
//отрисовка внутреннего круга — совокупности малых
//внутренних секторов
//установка цвета заливки
ms[number]. Item Image. Canvas. Brush. Color:=background;
//установка цвета линии
ms[number]. Item Image.Canvas. Pen.Colored White;
//отрисовка внутреннего круга
ms[number]. Item Image.Canvas. Ellipse(xi+xo-n/yi+yo-
r^xi+xo+r^yi+yo+n);
183
РАЗРАБОТКА SCADA-СИСТЕМ
//отрисовка цифр на шкалах движков изменения верней
//и нижней границ
for i:=o to 5 do
begin
//отрисовка цифр на движке изменения нижней границы
ms[number].ltemlmage.Canvas.TextOut(i*(ms[number]. Itm Down.
Width div 5 -2)+2,ms[number].Itemimage.Height-i5,lntToStr(i));
//отрисовка цифр на движке изменения верней границы
ms[number].ltemlmage.Canvas.TextOut(i*(ms[number].ltmllp.
Width div 5 -2)+2,ms[number].ltemlmage.Height-i5-
ms[number].ltmDown.Height-3OzlntToStr(i));
end;
//вывод надписи над движком изменения нижней границы
ms[number].ltemlmage.Canvas.TextOut(5zms[number]. Item Image.
Height-i5-ms[number].ltmDown.Height-15,1 НИЖНЯЯ ГРАНИЦА1);
//вывод надписи над движком изменения верхней границы
ms[number].ltemlmage.Canvas.TextOut(5zms[number]. Item Image.
Height-i5-ms[number].ltmDown.Height-3O-ms[number].ltmUp.
Height-15,1 ВЕРХНЯЯ ГРАНИЦА);
//отрисовка длинных рисок на диаграмме
for i:=o to 4 do
begin
//координата x начала риски
x:=xi+xo-round(xo*cos(i*4*ugl*gr));
//координата у начала риски
y:=yi+yo-round(yo*sin(i*4*ugl*gr));
// перемещение указателя в точку (х,у)
ms[number].ltemlmage.Canvas.MoveTo(x,y);
//координата х конца риски
x:=xi+xo-round((ri-5)*cos(i*4*ugl*gr));
// координата у конца риски
y:=yi47O-round((ri-5)*sin(i*4*ugl*gr));
//отрисовка риски
ms[number].ltemlmage.Canvas.LineTo(x,y);
end;
//оцифровка шкалы диаграммы (цифры от о до 4)
//первая цифра о
i:=o;
//координата х цифры о
x:=xi+xo-round(xo*cos(i*4*ugl*gr))+r2+5;
184
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
// координата у цифры о
y:=yi+yo+round(yo'A'sin(i'A'4'A'ugl'A'gr))-io;
И вывод цифры о на шкале диаграммы
ms[number].ltemlmage.Canvas.TextOut(xzyzlntToStr(i));
//цифра 1
inc(i);
//координата х цифры 1
x:=xi+xo^ound(xo*cos(i*4*ugl*gr))+5;
//координатау цифры 1
y:=yi+yo^ound(yo*sin(i*4*ugl*gr))+r2+5;
// вывод цифры 1 на шкале диаграммы
ms[number]. Item Image.Canvas.TextOut(xzyzlntToStr(i));
//цифра 2
inc(i);
//координата x цифры 2
x:=xi+xo-round(xo*cos(i*4*ugl*gr))-r2-io;
// координата у цифры 2
y:=yi+yo^ound(yo*sin(i*4*ugl*gr))+5;
// вывод цифры 2 на шкале диаграммы
ms[number]. Item Image.Canvas.TextOut(xzyzlntToStr(i));
// цифра з
inc(i);
//координата x цифры 3
x:=xi+xo-round(xo*cos(i*4*ugl*gr))-r2-io;
//координатау цифры3
y:=yi+yo^ound(yo*sin(i*4*ugl*gr))-r2-5;
// вывод цифры з на шкалу диаграммы
ms[number].ltemlmage.Canvas.TextOut(xzyzlntToStr(i));
//цифра 4
inc(i);
//координата х цифры 4
x:=xi+xo^ound(xo*cos(i*4*ugl*gr))+5;
//координатау цифры 4
y:=yi+yo-round(yo*sin(i*4*ugl*gr))-r2-2o;
// вывод цифры 4 на шкалу диаграммы
ms[number]. Item Image.Canvas.TextOut(xzyzlntToStr(i));
// вывод статуса в центре диаграммы
ms[number]. Item Image.Canvas. Font.Color:=Color;
//координата x статуса
x:=xi+xo-(ms[number],Itemimage.Canvas.TextWidth(ss) div 2);
// координата у статуса
y:=yi+yo-(ms[number],Itemimage.Canvas.TextHeight(ss) div 2);
185
РАЗРАБОТКА SCADA-СИСТЕМ
И вывод статуса
ms[number]. Item Image.Canvas.TextOut(xzyzss);
end;
//процедура вызова формы AddForm настроек сервера
procedure TMainForm.AddFormRunClick(Sender: TObject);
begin
//скрытие главной формы
MainForm.Hide;
//выключение таймера
Timeri. Enabled :=false;
//уничтожение сервера
Server:=nil;
// вызов дополнительной формы
AddForm.Show;
end;
//процедура обработки изменения верхних или нижних границ
И тегов
procedure TMainForm.TrackBarChange(Sender: TObject);
var
//движок, на котором произошло событие
trbar:TTrackBar;
begin
//определение движка, на котором произошло событие
trbar:=Sender asTTrackBar;
//если идентификационный номер движка меньше 8
if trbar.Tag<=7 then
begin
// если ползунок движка нижней границы оказался выше
//верхней границы
if ms[trbar.Tag].ItmDown.Position>=ms[trbar.Tag].ItmUp.Position
then
//установка ползунка движка нижней границы равным
//верхней границе
trbar. Position :=ms[trbar.Tag]. Itm Up. Position;
//установка нижней границы тега
ms[trbar.Tag].Down:=trbar.Position*s;
end
else
begin
186
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//если ползунок движка верхней границы оказался ниже
//нижней границы
if ms[trbar.Tag-io].ltmUp.Position<=ms[trbar.Tag-io].ltmDown.
Position then
//установка ползунка движка верхней границы равным нижней
//границе
trbar. Position :=ms[trbar.Tag-io]. Itm Down. Position;
//установка верхней границы тега
ms[trbar.Tag-io].Up:=trbar.Position*s;
end
end;
//действия, выполняемые при уничтожение формы
procedure TMainForm.FormDestroy(Sender: TObject);
begin
//уничтожение сервера
Server:=nil;
//обнуление динамического массива
SetLength(mszo);
end;
end.
2.6. Использование мультипликации в системах
визуализации информации
Все современные SCADA-системы так или иначе ограничива-
ют пользователя количеством используемых графических образов.
Разработка SCADA в среде визуального проектирования приложе-
ний Delphi свободна от этих недостатков: можно «монтировать»
любые графические образы, выводить их на поверхность формы в
любой последовательности, использовать звуковое сопровождение.
Рассмотрим пример. Требуется визуализировать положение
автоматических ворот по сигналу, поступающему с аналогового
датчика перемещения. На выходе этого датчика формируется на-
пряжение в диапазоне 0...+5 В. На самом деле с датчика снимает-
ся напряжение, лежащее в еще более узком диапазоне. В качестве
первого приближения можно использовать макет, рассмотренный
в главе 1.
187
РАЗРАБОТКА SCADA-СИСТЕМ
Рассмотрим проект, реализующий просмотр на экране в гра-
фической форме положение ворот. Ворота, открываясь, сдвигаются
влево, а закрываясь — вправо. Содержимое папки, хранящей все
файлы и папки проекта, приведено на рис. 2.24.
Рис. 2.24. Содержимое папки проекта Gate to Happiness
На рис. 2.25 приведено содержимое папки Pictures. Она содер-
жит папки Gatel, Samurai, Sceleton, Z1 и два рисунка China.bmp
и Cloud.bmp. Эти папки и рисунки содержат все необходимые гра-
фические образы, используемые в данном проекте.
188
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Bl Pictures
.JnLxl
Файл Правка Вид Избранное Сервис Справка
0Н4МД ’ О ’ Т ' z Пои® Папки £ £ X Ю
Адрес: | D:\KoHTponnep\Gate to HappinesslR :tores 30 Переход
IGatel
^Samurai
_j Seel eton
Ozi
China.bmp
'"1 Cloud.bmp
Рис. 2.25. Содержимое папки Pictures проекта
Папка Gatel (рис. 2.26) содержит три файла:
- Gatel_Average.bmp — изображение ворот в обычном мас-
штабе;
- Gatel_High.bmp — изображение ворот в увеличенном мас-
штабе;
- Gatel_Low.bmp — изображение ворот в уменьшенном мас-
штабе.
Gdtel_High.bmp
Gatel_Low.bmp
Рис. 2.26. Содержимое папки Gatei проекта
На ворота нанесено изображение самурая с мечом. Графи-
ческие образы самурая в различных масштабах хранятся в папке
Samurai в файлах Samurika_Average.bmp, Samurika_High.bmp,
Samurika_Low.bmp (рис. 2.27).
189
РАЗРАБОТКА SCADA-СИСТЕМ
Bl Samurai
Файл Правка Вид Избранное Сервис Справка I &
Q Назад ’ Q ’ | /Р Поиск Папки I£ X. *0 | ЕП1’
Адрес; | D:\KoHTponnep\Gate to Happiness\Pfctures^Samurai за Переход
Д Samurika.bmp
Л] Samurika_Average .bmp
*У| 5amurika_fGgh. bmp
?2J Samurika J.OW. bmp
Рис. 2.27. Папка с изображениями самурая в разных масштабах
Когда ворота открываются, то за ними проглядывается зло-
вещая фигура скелета с кинжалом. Графические образы скелета
в различных масштабах хранятся в папке Sceleton в файлах
Sceleton_Average.bmp, Sceleton _High.bmp, Sceleton_Low.bmp
(рис. 2.28)
Sv Sceleton
Г.'1 Sceleton.bmp
Sceleton_Average.bmp
Sceleton_High.bmp
Sceleton JLow. bmp
Рис. 2.28. Папка с изображениями скелета в разных масштабах
Забор состоит из фрагментов трех типов (рис. 2.29):
- правый фрагмент забора;
- центральный фрагмент забора;
- левый фрагмент забора.
190
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Их графические образы в различных масштабах находятся
в папке Z1, которая присутствует в папке Picturies (рис. 2.30).
Файл Правка Вид Избранное Сервис Справка
Назад - Поиск [ Папки [777]^
Адрес: ]_J 0:\Контроллер\Са1е to Happiness\Pktures^Zl |Я Переход
Zl_Center_Average.bmp
Л] Zl_Center_High.bmp
'"1Z1 _Center_Low .bmp
Z13efCAverage.bmp
'"1 Zl_Left_High.bmp
:2J Z1 _Left_Low.bmp
'"] Z1 _Right_Average .bmp
Z l^Right Jiiqh. bmp
%] Z l_Right J.ow. bmp
Рис. 2.30. Графические образы разных частей забора в различных
масштабах в папке Z1
Скрежет ворот при их открытии или закрытии выводится через
стереоколонки. Звук скрежета находится в файле Gate.wav, который
расположен в папке Sound (рис. 2.31).
to Sound
^Gate.wav
Рис. 2.31. Расположение файла звукового сопровождения
На рис. 2.32, 2.33, 2.34 приведены изображения выводимой
на экран графики в трех возможных масштабах и при различ-
ных положениях ворот (закрыты, приоткрыты, полностью откры-
ты).
191
РАЗРАБОТКА SCADA-СИСТЕМ
it.... .—1 ......;'
!!!!Н!!»»йа t»!££2
Рис. 2.32. Выводимая графика при закрытых воротах
Рис. 2.33 . Выводимая графика при полуоткрытых воротах
192
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Рис. 2.34. Выводимая графика при полностью открытых воротах
В данном проекте используются две формы: AddForm
и MainForm. Внешний вид формы AddForm приведен на рис. 2.35.
С помощью этой формы выполняются следующие действия:
- ввод имен сервера, сегмента и узла сети;
- ввод числа каналов (тегов), используемых для просмотра;
в нашем случае используется один канал, т. к. датчик пере-
мещения ворот тоже один;
- ввод имени тега (переменной, снимаемой с датчика пере-
мещения ворот); имя тега обязательно должно совпадать
с именем переменной, используемой в программе, напи-
санной на языке UltraLogik и работающей в данное время
в контроллере ADAM-5510;
- запуск ОРС-сервера с помощью кнопки «Сервер»;
- переход к главной форме с помощью кнопки ОК.
193
РАЗРАБОТКА SCADA-СИСТЕМ
Рис. 2.35. Общий вид формы AddForm
На рис. 2.36 показаны все компоненты формы AddForm (кро-
ме таймера), используемые в данном проекте, и указаны их имена.
ввода числа Logo
тегов
запуска ОРС- ОК вызова ввода имен
сервера MainForm тегов
Рис. 2.36. Форма AddForm с пояснениями
Модуль AddUnit
На рис. 2.37 показаны все графические элементы, располагае-
мые на форме MainForm.
194
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Облако
Фон
Back
Cloud
Средняя часть Правая часть Левая часть
забора ZbrCenter забора Zb гRight забора ZbrLeft
Рис. 2.37. Все графические элементы, расположенные на форме MainForm
При работе данного приложения, как и в ранее рассмотренных
просмотрщиках тегов, используется загрузка имен сервера, сегмен-
та, узла, числа тегов, имен тегов перед началом работы из файла
AutoSave.sav. Структура этого файла показана на рис. 2.38.
C AutoSave.sav - Блокнот
Файл Правка Формат Вид Справка
Fastwel .PLCNetOPC И
llltranet_l
FD
1
datchi k
Рис. 2.38. Структура файла AutoSave.sav
195
РАЗРАБОТКА SCADA-СИСТЕМ
Свойства формы AddForm и ее компонентов, а также все дей-
ствия, выполняемые с ее помощью, определяются процедурами
и функциями модуля AddUnit. Модуль AddUnit с подробными
комментариями приведен ниже. Структура модуля AddUnit и дей-
ствия, выполняемые с помощью его процедур и функций, весьма
похожи на ранее рассмотренные в других просмотрщиках тегов.
Рассмотрим действия, выполняемые в основных процедурах этого
модуля.
Процедура TAddForm.FormCreate
Выполняет следующие действия:
- выключает ОРС-сервер Server;
- выключает таймер Timer 1;
- создает динамический массив тегов Items (в нашем случае
его длина равна единице);
- заполняет символом «О» поле величин тегов;
- задает цвет, геометрические размеры формы и ее располо-
жение на экране;
- создает на форме панель Panell и располагает на ней окна
Srv, Sgt и Node для ввода в них имен сервера, сегмента и
узла соответственно; задает свойства всех этих компонен-
тов;
- создает на форме панель Рапе12 и располагает на ней окно
Number для ввода числа тегов (у нас он один), таблицу Itms
для ввода имени тегов и задает свойства всех этих компо-
нентов;
- создает в левом нижнем углу логотип Logo и задает его
свойства;
- создает кнопку Srvr с надписью «Сервер» и задает ее свой-
ства;
- создает кнопку ОК с надписью ОК и задает ее свойства;
- осуществляет поиск файла AutoSave.sav и читает из него
имена сервера, сегмента, узла, число тегов (1), имена тегов
(тега), которые были использованы в предыдущем сеансе
работы;
- осуществляет заполнение ячеек таблицы Itms в соответ-
ствии с именами тегов, прочитанных из файла AutoSave.sav.
196
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Процедура TAddForm.NumberChange
Вызывается всякий раз, когда происходит изменение содержи-
мого в окне Number ввода числа тегов. Она выполняет следующие
действия:
- отключает таймер Timer 1;
- определяет число тегов, обслуживаемых данным приложе-
нием;
- обнуляет исходные значения тегов;
- заполняет ячейки таблицы Itms исходными именами тегов:
Vxodl, Vxod2 и т. д.
Процедура TAdd Form.NumberKeyPress
Вызывается при вводе информации в окно Number ввода чис-
ла тегов. Она разрешает действия клавиш 0.. .9 и Backspace.
Процедура TAddForm.SrvrClick
Вызывается в случае щелчка мышью по кнопке Srvr («Сер-
вер»). Она запускает ОРС-сервер и проверяет результат запуска.
Если запуск ОРС-сервера происходит с ошибкой, то выводится со-
общение: «Не могу запустить сервер!!!»
Процедура TAddForm.OKClick
Вызывается при щелчке мышью на кнопке ОК и реализует
действия по переходу к основной форме MainForm. Процедура вы-
полняет следующие действия:
- проверяет число тегов и, если оно равно нулю, выводит со-
общение «Необходимо добавить хотя бы один канал!!!»;
- отключает таймер Timer 1;
- включает ОРС-сервер, добавляет в него сегмент, а затем и
теги, причем все эти действия контролируются и при воз-
никновении ошибки немедленно прекращаются; имена
ОРС-сервера, сегмента узла и тегов берутся из окон ввода
Srv, Sgt, Node и таблицы Itms соответственно;
- включает таймер Timerl;
- вызывает процедуру InitGraf из модуля Main, которая бу-
дет рассмотрена далее;
- вызывает главную форму MainForm.
197
РАЗРАБОТКА SCADA-СИСТЕМ
Процедура TAddForm.FormClose
Вызывается при щелчке мышью на кнопке закрытия приложе-
ния. Она выполняет следующие действия:
- записывает в файл AutoSave.sav имена ОРС-сервера, сег-
мента, узла, тегов, которые использовались в данном сеансе
работы;
- выключает таймер Timer 1;
- выключает ОРС-сервер;
- закрывает приложение.
Процедура TAddForm.FormDestroy
Вызывается при щелчке мышью на кнопке закрытия приложе-
ния. Она выключает ОРС-сервер и уничтожает динамический мас-
сив тегов Items.
Процедура TAddForm.TimerlTimer
Вызывается сигналами, поступающими с таймера Timerl. Она
выполняет следующие действия:
- чтение из сети величин всех тегов и качества их приема
ОРС-сервером;
- запись полученных величин тегов и качества их приема
ОРС-сервером в динамический массив Items.
Модуль Main
Содержит процедуры и функции, которые используются для
отрисовки графических построений на основной форме MainForm.
В разделе констант объявлена константа оЫ = 10, которая ука-
зывает на то, что над графическим пейзажем будут плыть слева на-
право 10 облаков.
В разделе объявления переменных объявлены следующие пе-
ременные:
- Bkgrnd: TImage — холст, на котором будет рисоваться гра-
фическое изображение;
- ZbrCenter, ZbrLeft, ZbrRight: TBitmap — переменные
для хранения графических образов центрального, левого
и правого фрагментов забора (рис. 2.29);
198
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
- Gate: TBitmap — переменная для хранения графического
образа ворот, которые при их отрывании сдвигаются влево;
- Sceleton: TBitmap — переменная для хранения графиче-
ского образа скелета, находящегося за воротами;
- Back: TBitmap — переменная для хранения графического
образа пейзажа за забором — пагода, деревья, ландшафт;
- Cloud: TBitmap — переменная для хранения графического
образа одного облака;
- Center, Left, Right: integer — ширина ворот, ширина левого
забора и ширина правого забора соответственно;
- Scale: byte — масштаб отрисовки изображений: 1 — малый;
2 — средний; 3 — большой; изменение масштаба осущест-
вляется колесом мыши;
- dt, olddt: real — переменные для хранения нового и старого
значений тега;
- оо: array of record — динамический массив для хранения
координат хну всех десяти облаков и шага перемещения
для каждого облака.
Процедура TMainForm.FormCreate
Вызывается во время создания формы MainForm. Она выпол-
няет следующие действия:
- выключает оба используемых таймера Timerl и Timer!;
- устанавливает интервалы работы обоих таймеров: 10
и 500 мс соответственно;
- задает геометрические размеры формы во весь экран;
- задает цвет формы;
- выбирает файл Sound\Gate.wav для проигрывания его на
медиаплейере MediaPlayer 1; этот файл содержит скрежет
перемещения ворот;
- создает поверхность (холст) для рисования Bkgrnd:TImage
и задает его свойства: расположение на экране, высота, ши-
рина, авторазмер, автомасштабирование.
Процедура InitGraph
Использована в модуле AddUnit и выполняет подготовитель-
ные функции:
199
РАЗРАБОТКА SCADA-СИСТЕМ
- задает начальное значение масштаба: scale = 1;
- создает динамический массив оо координат облаков длиной
в 10 компонентов;
- создает все используемые в приложении битовые образы
(графические изображения): ZbrCenter, ZbrLeft, ZbrRight,
Gate, Sceleton, Back, Cloud;
- загружает битовые образы Back и Cloud (пейзаж и облако)
из файлов Pictures\China.bmp и Pictures\Cloud.bmp соот-
ветственно;
- случайным образом определет координаты х и у всех десяти
облаков, а также величины шага их перемещения;
- включает таймеры Timerl и Timer!;
- записывает величину тега из массива Items в переменную
olddt.
Процедура TMainForm.FormClose
Вызывается в случае закрытия формы MainForm щелчком
мыши на кнопке закрытия приложения. Эта процедура выполняет
следующие действия:
- выключает таймеры Timerl и Timer!;
- уничтожает все используемые графические образы путем
освобождения динамической памяти, которая использова-
лась для их хранения;
- уничтожает динамический массив оо путем обнуления его
длины;
- закрывает файл MediaPlayerl.FileName, хранящий звук
скрежета ворот при их перемещении.
Процедура Graph(Prozent:integer)
Предназначена для вывода на экран всего комплекса гра-
фических изображений, используемых в данном приложении.
Процедура имеет параметр Prozent:integer, который определяет
положение ворот. Параметр Prozent полностью зависит от вели-
чины тега, хранящегося в переменной Items[0] .ItemValue. При
Prozent = 0 ворота полностью открыты, при Prozent = 100 воро-
та полностью закрыты. Процедура выполняет следующие дей-
ствия:
200
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
- в зависимости от масштаба изображения, определяемого
переменной scale (принимает значения 1, 2 или 3) загружает
в переменные ZbrCenter, ZbrLeft, ZbrRight, Gate, Sceleton
из соответствующих файлов графические образы компонен-
тов композиции, выводимой на экран;
- определяет ширину ворот Center, причем чем больше мас-
штаб Scale, тем больше значение переменной Center;
- по значению величины Center вычисляет ширину левого
и правого заборов: Left, Right;
- определяет непосредственно из параметров ZbrCenter.
Width, ZbrCenter.Height переменные zw и zh, задающие
ширину и высоту одного фрагмента забора;
- устанавливает свойство прозрачности Transparent в true для
компонентов ZbrCenter, ZbrLeft, ZbrRight, Gate, Sceleton;
- отрисовывает скелет Sceleton, ворота Gate;
- отрисовывает левую часть забора путем многократного вы-
вода на экран слева направо центрального фрагмента забо-
ра; последним (правым) элементом является левый фраг-
мент забора (рис. 2.29, а);
- отрисовывает правую часть забора путем многократного
вывода на экран слева направо центрального фрагмента за-
бора; первым (левым) элементом является правый фрагмент
забора (рис. 2.29, в).
Процедура TMainForm.TimerlTimer
Вызывается всякий раз, когда поступает очередной сигнал
с таймера Timerl. Процедура выполняет следующие действия:
- записывает в переменную dat величину тега из ячейки
Items [0].Item Value; по величине dat вычисляется процент
рг открытости ворот
pr = dat х ЮО / 9000,
который затем используется в качестве параметра в проце-
дуре отрисовки графики Graph;
- выводит на экран фон Back;
- выводит на экран в цикле с помощью процедуры Draw де-
сять облаков, причем координата х каждого из них готовится
201
РАЗРАБОТКА SCADA-СИСТЕМ
заранее и содержится в массиве оо; координаты у каждого
облака и шаг его перемещения s задаются в тот момент, когда
облако уходит за пределы экрана;
- вызывает процедуру Graph с новым значением параметра
Prozent, равным величине рг.
Процедура TMainForm.MouseWheelUp
Вызывается всякий раз, когда пользователь передвинул колесо
мыши вверх. Колесо мыши используется в данном приложении для
изменения масштаба scale выводимого на экран изображения. Вели-
чина scale может принимать значения 1,2 и 3. Процедура выполняет
следующие действия:
- увеличивает величину scale на 1;
- выполняет проверку величины scale; если scale превы-
шает 3, то ей присваивается максимальное значение 3;
- выполняет вывод заголовка формы в соответствии с мас-
штабом.
Процедура TMainForm.MouseWheelDown
Вызывается, если произошло перемещение колеса мыши вниз.
Процедура выполняет следующие действия:
- уменьшает значение переменной scale на 1;
- выполняет проверку полученного значения scale; если
оно меньше или равно 0, то scale присваивается значе-
ние 1;
- в соответствии с величиной scale формирует заголовок фор-
мы MainForm.
Процедура TMainForm.Timer2Timer
Возникает каждый раз, когда поступает сигнал с таймера . Пе-
риод этого сигнала составляет 500 мс. Процедура выполняет следу-
ющие действия:
- заносит в переменную dt величину тега;
- проверяет состояние Position медиаплейера MediaPlayerl;
если он закончил очередное проигрывание звука скрежета
перемещаемых ворот, то проигрывание этого звука возоб-
новляется;
202
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
- сравнивает новое значение dt величины тега и старое его
значение olddt, которое было во время предыдущего выпол-
нения процедуры TMainForm.Timer2Timer; если их раз-
ность не превышает величины 2, то медиаплейер останав-
ливается и проигрывание звука прекращается (это означает,
что ворота остановились);
- заносит значение переменной dt в переменную olddt.
Процедура TMainForm.FormKeyPress
Выполняется всякий раз, когда нажимается любая клавиша на
клавиатуре. Она проверяет, не была ли нажата клавиша Esc (код 27).
Если была нажата клавиша Esc, то выполняется закрытие формы
MainForm.
Программный код модуля AddUnit
Листинг 2.6
unit AddUnit;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics,
Controls, Forms,
Dialogs, ExtCtrls, StdCtrls, Grids, CheckLst, OPCDA, OPCTypes,
OPCUtils, ComObj, ActiveX,
DB, DBCIient, MConnect, SConnect;
type
TAddForm = class(TForm)
//таймер
Timeri: TTimer;
//действия при создании формы
procedure FormCreate(Sender: TObject);
//обработка нажатия какой-либо клавиши при вводе информации
//в окно ввода Number
procedure NumberKeyPress(Sender: TObject; var Key:Char);
//действия при изменении текста в окне ввода Number
procedure NumberChange(Sender:TObject);
203
РАЗРАБОТКА SCADA-СИСТЕМ
//обработка щелчка мыши на кнопке «Сервер»
procedure SrvrClick(Sender:TObject);
//обработка щелчка мыши на кнопке ОК
procedure OKCIick(Sender:TObject);
//действия при закрытии формы AddForm
procedure FormClose(Sender: TObject; var Action: TCIoseAction);
//действия при уничтожении формы
procedure FormDestroy(Sender: TObject);
//реакция на сигналы, поступающие с таймера
procedure TimenTimer(Sender: TObject);
private
{Private declarations}
public
{Public declarations}
end;
var
//форма настройки
AddForm: TAddForm;
// цвет фона
background:TColor;
//панели
Paneli, Panel 2:TPanel;
//кнопки OK и «Сервер»
OK,Srvr:TButton;
//логотип
Logo:Tlmage;
//окна для ввода имен сервера, сегмента и узла
Srv,Sgt,Node:TLabeledEdit;
//окно для ввода числа каналов
Number:TLabeledEdit;
//таблица для ввода названий каналов
ltms:TStringGrid;
//переменная, которая хранит результат операции
HR:HRESULT;
//интерфейс, с помощью которого осуществляется добавление
// тегов в сегмент и их удаление
SegmentdOPCItemMgt;
//хэндл сегмента
SegmentHandle:OPCHANDLE;
//количество каналов
minteger;
//переменная для связи с ОРС-сервером на мастере
204
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
ServerdOPCServer;
И массив тегов
ltems:array of record
И имя тега
ltemName:string;
//хэндл тега
ltemHandle:OPCHANDLE;
//тип тега
ItemTypeTVarType;
//величина тега
ltemValue:string;
//качество связи тега
ltemQuality:word;
end;
implementation
uses Main;
{$R *.dfm}
//процедура no созданию формы настройки
procedure TAddForm.FormCreate(Sender: TObject);
var
//счетчик цикла
idnteger;
//переменная для вычисления размеров компонентов
//(ширины, высоты и т.д.)
pnreal;
//файловая переменная
f:TextFile;
//переменная, в которую считываются строки из файла
s:string;
begin
//начальное значение
Segment:=nil;
//сервер выключен
Server:=nil;
//выключение таймера
Timen. Enabled :=false;
//интервал таймера (юо мс)
Timeri. Interval:=юо;
//число каналов по умолчанию
п:=8;
//установка длины Items в п
SetLength(ltemszn);
205
РАЗРАБОТКА SCADA-СИСТЕМ
//заполнение полей величин тегов в динамическом массиве
//нулями
for i:=o to n-i do
ltems[i]. Item Vai ue:='o';
//настройки дополнительной формы
// цвет фона
background:=RGB(ioozi5Oz2Oo);
pr:=5o;
//ширина компонента
Add Form .Width :=round((Monitor.Width/ioo)*pr);
pr:=34;
//высота компонента
Add Form. Height:=round((Monitor.Height/ioo)*pr);
//позиция дополнительной формы на дисплее в центре монитора
Add Form. Position :=poScreenCenter;
//заголовок дополнительной формы
Add Form. Caption :='Настройка ОРС-сервера1;
//стиль границ дополнительной формы
AddForm. BorderStyle:=bsSingle;
//разрешена кнопка закрытия формы
Add Form. Borderlcons:=[biSystem Menu];
//цвет дополнительной формы
Add Form. Color:=background;
//создание панели Paneh, на которой расположены окна
И ввода имен сервера, сегмента и узла
//создание компонента
Paneli:=TPanel.Create(Self);
//родитель компонента
Paneli.Parent:=AddForm;
рг:=1;
//ордината левого верхнего угла компонента
Paneli.Top:=round((Monitor.Height/ioo)*pr);
рг-0.5;
//абсцисса левого верхнего угла компонента
Paneli.Left:=round((Monitor.Width/ioo)*pr);
рг-48.5;
//ширина компонента
Paneli.Width :=round((Monitor.Width/ioo)*pr);
рг:=8;
//высота компонента
206
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Paneli. Height:=round((Monitor.Height/ioo)*pr);
//стиль внутренней границы компонента
Paneli. Bevel lnner:=bvRaised;
//стиль внешней границы компонента
Paneli. BevelOuter:=bvl_owered;
//цвет компонента
Paneli. Color:=background;
//создание окна для ввода имени сервера
//создание компонента
Srv:=TI_abeledEdit.Create(Self);
//родитель компонента
Srv.Parent:=Paneli;
рг:=з;
//ордината левого верхнего угла компонента
Srv.Top:=round((Monitor.Height/ioo)*pr);
рг-1.5;
//абсцисса левого верхнего угла компонента
Srv.Left:=round((Monitor.Width/ioo)*pr);
//авторазмер компонента
Srv.AutoSize:=false;
//размер шрифта компонента
Srv.Font.Size:=io;
//цвет компонента
Srv.Color:=background;
рг:=з;
//высота компонента
Srv.Height:=round((Monitor.Height/ioo)*pr);
рг-17;
//ширина компонента
Srv.Width:=round((Monitor.Width/ioo)*pr);
//заголовок компонента
Srv.EditLabel.Caption:='OPC-Server';
//свойство text компонента
Srv.Text:='Fastwel.PLCNetOPC';
//создание окна для ввода имени сегмента
//создание компонента
Sgt:=TI_abeled Ed it.Create(Self);
//родитель компонента
Sgt.Parent:=Paneli;
рг:=з;
207
РАЗРАБОТКА SCADA-СИСТЕМ
//ордината левого верхнего угла компонента
Sgt.Top:=round((Monitor.Height/ioo)*pr);
рг:=2О;
//абсцисса левого верхнего угла компонента
Sgt.Left:=round((Monitor.Width/ioo)*pr);
//авторазмер компонента
Sgt.AutoSize:=false;
//размер шрифта компонента
Sgt. Font. Size:=io;
//цвет компонента
Sgt.Color:=background;
рг:=з;
//высота компонента
Sgt.Height:=round((Monitor.Height/ioo)*pr);
рг-17;
//ширина компонента
Sgt. Width :=round((Monitor.Width/ioo)*pr);
//заголовок компонента
Sgt. EditLabel. Caption :='Сегмент UltraNet1;
//свойство text компонента
Sgt.Text:='Ultranet_i';
//создание окна для ввода имени узла
//создание компонента
Node:=TLabeled Edit.Create(Self);
//родитель компонента
Node.Parent:=Paneli;
рг:=з;
//ордината левого верхнего угла компонента
Node.Top:=round((Monitor.Height/ioo)*pr);
рг-38.5;
//абсцисса левого верхнего угла компонента
Node.Left:=round((Monitor.Width/ioo)*pr);
//авторазмер компонента
Node.AutoSize:=false;
//размер шрифта компонента
Node. Font. Size:=10;
//цвет компонента
Node.Color:=background;
рг:=з;
//высота компонента
Node.Height:=round((Monitor.Height/ioo)*pr);
208
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
рг:=8.5;
//ширина компонента
Node. Width :=round((Monitor.Width/ioo)*pr);
//заголовок компонента
Node. EditLabel.Caption :='Узел';
//свойство text компонента
Node.Text-'FE1;
//создание панели Panel2
Panel2:=TPanel.Create(Self);
//родитель компонента
Panel2.Parent:=AddForm;
pr:=io;
//ордината левого верхнего угла компонента
Panel2.Top:=round((Monitor.Height/ioo)*pr);
рг-0.5;
//абсцисса левого верхнего угла компонента
Panel2.Left:=round((Monitor.Width/ioo)*pr);
рг-48.5;
//ширина компонента
Panel2.Width:=round((Monitor.Width/ioo)*pr);
рг:=2О;
//высота компонента
Panel2.Height:=round((Monitor.Height/ioo)*pr);
//стиль внутренней границы компонента
Panel2.Bevellnner:=bvRaised;
//стиль внешней границы компонента
Panel2.BevelOuter:=bvLowered;
//цвет компонента
Panel2.Color:=background;
//создание окна Number для ввода числа каналов (тегов)
Number:=TLabeledEdit.Create(Self);
//родитель компонента
Number. Parent:=Panel2;
рг:=з;
//ордината левого верхнего угла компонента
Number.Top:=round((Monitor.Height/ioo)*pr);
рг-1.5;
//абсцисса левого верхнего угла компонента
Number. Left:=round((Monitor.Width/ioo)*pr);
//авторазмер компонента
209
РАЗРАБОТКА SCADA-СИСТЕМ
Number. AutoSize:=false;
//размер шрифта компонента
Number. Font. Size:=io;
//цвет компонента
Number.Color:=background;
рг:=з;
//высота компонента
Number. Height:=round((Monitor. Height/ioo)*pr);
pr:=ii;
//ширина компонента
Number.Width:=round((Monitor.Width/ioo)*pr);
//заголовок компонента
Number.EditLabel.Caption^'Hi/icno каналов1;
//свойство text компонента
Number.Text:='8';
//событие OnKeyPress компонента
Number.OnKeyPress:=Numberl<eyPress;
//событие OnChange компонента
Number.OnChange:=NumberChange;
//создание таблицы Itms для ввода имен тегов
ltms:=TStringGrid.Create(Self);
//родитель компонента
ltms.Parent:=Panel2;
рг-14;
//абсцисса левого верхнего угла компонента
ltms.Left:=round((Monitor.Width/ioo)*pr);
рг:=1;
//ордината левого верхнего угла компонента
ltms.Top:=round((Monitor.Height/ioo)*pr);
рг:=зз;
//ширина компонента
Itms.Width :=round((Monitor.Width/ioo)*pr);
pr:=io;
//высота компонента
ltms.Height:=round((Monitor.Height/ioo)*pr);
//цвет компонента
ltms.Color:=background;
//цвет фиксированных строк и столбцов компонента
ltms.FixedColor:=background;
//число столбцов компонента
ltms.ColCount:=n+i;
210
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
// число строк компонента
ltms.RowCount:=2;
рг:=8;
//ширина столбцов компонента
Itms. Defaulted Width :=round((Monitor.Width/ioo)*pr);
//заполнение ячеек таблицы имен каналов (тегов)
Itms.CellstO/Oj^'Hoiviep1;
Itms.Cel 15[о/п]:='Имя|;
for i:=i to n do
begin
Кт5.Се115[1/о]:='Канал '+lntToStr(i);
ltms.Cells[i/i]:='Vxodl+lntToStr(i);
end;
//настройка компонента на возможность
//редактирования текста в ячейке (1,1)
ltms.Options:=[goFixedVertLinezgoFixedHorzLinezgoVertLinez
goHorzLine,
goRangeSelectzgoEditing];
//создание логотипа
Logo:=Tlmage.Create(Self);
//родитель компонента
Logo.Parent:=Panel2;
pr-1.5;
//абсцисса левого верхнего угла компонента
Logo.Left:=round((Monitor.Width/ioo)*pr);
рг:=11;
//ордината левого верхнего угла компонента
Logo.Top:=round((Monitor.Height/ioo)*pr);
pr:=io;
//ширина компонента
Logo.Width :=round((Monitor.Width/ioo)*pr);
рг-7;
//высота компонента
Logo.Height:=round((Monitor.Height/ioo)*pr);
//загрузка картинки
Logo. Picture. Load From File('AM.bmp');
//создание кнопки «Сервер»
Srvr:=TButton.Create(Self);
//родитель компонента
211
РАЗРАБОТКА SCADA-СИСТЕМ
Srvr.Parent:=Panel2;
//заголовок компонента
Srvr.Caption:='CepBep';
pr-17;
//абсцисса левого верхнего угла компонента
Srvr.Left:=round((Monitor.Width/ioo)*pr);
рг-14;
//ордината левого верхнего угла компонента
Srvr.Top:=round((Monitor.Height/ioo)*pr);
рг:=6;
//ширина компонента
Srvr.Width:=round((Monitor.Width/ioo)*pr);
РГ:=3-5;
//высота компонента
Srvr.Height:=round((Monitor.Height/ioo)*pr);
//событие OnClick компонента
Srvr.OnCI ick:=SrvrCI ick;
//создание кнопки ОК
OK:=TButton.Create(Self);
//родитель компонента
OK.Parent:=Panel2;
//заголовок компонента
OK.Caption-'OK1;
рг-31;
//абсцисса левого верхнего угла компонента
OK.Left:=round((Monitor.Width/ioo)*pr);
рг-14;
//ордината левого верхнего угла компонента
OK.Top:=round((Monitor.Height/ioo)*pr);
рг:=6;
//ширина компонента
OK.Width:=round((Monitor.Width/ioo)*pr);
Рг:=3-5;
//высота компонента
OK.Height:=round((Monitor.Height/ioo)*pr);
//событие OnClickкомпонента
OK.OnClick:=OKCIick;
//поиск файла AutoSave.sav в текущем каталоге и чтение
//из него имен сервера, сегмента, узла, числа каналов
И (тегов), имен тегов, которые были в предыдущем
И сеансе работы
212
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//если файл существует
if FileExists('AutoSave.sav') then
begin
И связь файловой переменной с файлом
Assign File(f, 'AutoSave.sav1);
//открытие файла для чтения
Reset(f);
//чтение имени сервера
readings);
//свойство text окна Srv
Srv.Text:=s;
//чтение имени сегмента
readings);
//свойство text окна Sgt
Sgt.Text:=s;
//чтение имени узла
readings);
//свойство text окна Node
Node.Text:=s;
//чтение числа каналов
readings);
// свойство text окна Number
Number.Text:=s;
//если свойство text состоит из нуля символов
if Number.Text=" then
//число каналов
п:=о
else
//число каналов
n:=StrTolnt(Number.Text);
//установка длины динамического массива
SetLength(ltemszn);
//цикл по п каналам
for i:=o to n-i do
//начальное значения величины переменной
ltems[i].ltemValue:='ol;
//число столбцов в таблице Itms имен переменных
ltms.ColCount:=n+i;
// если число каналов не равно нулю
if noo then
begin
//число фиксированных столбцов в таблице имен переменных
213
РАЗРАБОТКА SCADA-СИСТЕМ
ltms.FixedCols:=i;
//цикл по п каналам
for i:=i to n do
begin
//содержимое ячеек нулевой строки
Ит5.Се115[!/о]:='Канал '+lntToStr(i);
// содержимое ячеек первой строки, содержащей имена
//(имя) тегов
Itms.Cel ls[i/i]:='Vxodl+lntToStr(i);
end;
end;
//чтение имен переменных
for i:=o to n-i do
begin
//чтение имени переменной
readings);
//заполнение содержимого первой строки из файла
// AutoSav.sav
Itms. Cel I s[i+izi]:=s;
end;
//закрытие файла
CloseFile(f);
end;
end;
//процедура, обслуживающая изменение текста
И в окне Number
procedure TAddForm.NumberChange(Sender: TObject);
var
//счетчик цикла
i:integer;
begin
//отключение таймера
Timeri. Enabled :=false;
// если свойство text состоит из нуля символов
if Number.Text=" then
// число каналов
n:=o
else
//число каналов
n:=StrTolnt(Number.Text);
//установка длины динамического массива
214
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
SetLength(ltemszn);
//цикл по п каналам
for i:=o to n-i do
//начальное значения величины тега
ltems[i]. Item Vai ue:='o';
//числа столбцов в таблице имен тегов
ltms.ColCount:=n+i;
// если число каналов не равно нулю
if noo then
begin
//число фиксированных столбцов в таблице имен тегов
ltms.FixedCols:=i;
//цикл по п каналам
for i:=i to n do
begin
//содержимое ячеек нулевой строки таблицы имен тегов
Кт5.Се115[1/о]:='Канал '+lntToStr(i);
//содержимое ячеек первой строки таблицы имен тегов
ltms.Cells[izi] Vxod'+I ntToStr(i);
end;
end;
end;
//процедура, возникающая при вводе информации
// в окно Number
procedure TAddForm.NumberKeyPress(Sender: TObject;
var Key: Char);
begin
case key of
//разрешенные символы
else
//остальные запрещены
key:=#o;
end;
end;
//процедура, вызываемая при щелчке мышью
//по кнопке Srv («Сервер»)
procedure TAddForm.SrvrClick(Sender: TObject);
begin
try
215
РАЗРАБОТКА SCADA-СИСТЕМ
//запуск ОРС-сервера
Server:=CreateComObject(ProglDToClasslD(Srv.Text)) as lOPCServer;
// если произошла ошибка
except
// вывод сообщения об ошибке
ShowMessage('He могу запустить сервер!!!1);
//уничтожение сервера
Server:=nil;
end;
end;
//процедура, вызываемая щелчком мыши по кнопке ОК
procedure TAddForm.OKCIick(Sender: TObject);
var
//счетчик цикла
i:integer;
begin
// если число каналов равно нулю
if n=o then
begin
//сообщение
ShowMessage('Heo6xoAMMO добавить хотя бы один канал!!!1);
//выход из процедуры
exit;
end;
//отключение таймера
Timen. Enabled :=false;
//отключение сервера
Server:=nil;
try
//включение сервера
Server:=CreateComObject(ProglDToClasslD(Srv.Text)) as lOPCServer;
// если не смогли создать сервер
except
// вывод сообщения об ошибке
ShowMessage('He могу запустить сервер!!!1);
//уничтожение сервера
Server:=nil;
//выход из процедуры
Exit;
end;
// если сегмент Ultranet не добавлен
216
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
if Segment=nil then
//добавление сегмента в сервер
HR:=ServerAddGroup(Server,Sgt.Text,true,500,о,Segment,
SegmentHandle);
//если произошла ошибка
if Failed(HR) then
begin
//вывод сообщения об ошибке
ShowMessagefHe могу добавить сегмент UltraNet!!!1);
//уничтожение сервера
Server:=nil;
//выход из процедуры
Exit;
end;
//добавление тегов в сегмент
for i:=o to n-i do
begin
//полное имя тега
ItemsfiJ. Item Name:=Sgt.Text+'.l+Node.Text+'.l+ltms.Cel ls[i+izi];
//если переменной не существует
if ltems[i].ltemHandle=o then
//добавление тега
HR:=GroupAddltem(Segmentz ItemsfiJ. Item Name,
SegmentHandle,VT_EM PTY, ltems[i]. Item Handle, ltems[i].ltemType);
// если произошла ошибка
if Failed(HR) then
begin
// вывод сообщения об ошибке
ShowMessage('He могу добавить переменную '+
ltems[i].ltemName+l!!!');
//уничтожение сервера
Server:=nil;
//выход из процедуры
Exit;
end;
end;
//разрешение работы таймера
Timen. Enabled :=true;
// вызов процедуры из модуля Main
InitGraph;
// вызов формы MainForm
Main Form. Show;
end;
217
РАЗРАБОТКА SCADA-СИСТЕМ
//процедура, вызываемая при закрытии формы
procedureTAddForm.FormClose(Sender:TObject; var Action:
TCIoseAction);
var
//переменная для хранения выбранного действия пользователя
inf:Word;
//файловая переменная
f:TextFile;
//счетчик цикла
kinteger;
begin
//вызов диалогового окна для закрытия формы
inf:=MessageDlg('Вы уверены?1,mtlnformationz[mbYeszmbNo]zo);
// если нажата кнопка Yes
if inf=mrYes then
begin
// связь файловой переменной с файлом
AssignFile(f, 'AutoSave, sav1);
//перезапись файла
Rewrite(f);
//запись в файл имени сервера
writeln(f,Srv.Text);
//запись в файл имени сегмента
writeln(f,Sgt.Text);
//запись в файл имени узла
writeln(f,Node.Text);
//запись в файл каналов
writeln(f,number.text);
//запись в файл имен тегов
for i:=o to n-i do
//запись названия переменной
writeln(f, ltms.Cells[i+i,i]);
//закрытие файла
CloseFile(f);
//выключение таймера
Timen. Enabled :=false;
//выключение сервера
Server:=nil;
//обнуление длины динамического массива
SetLength(ltems,o);
//разрешение на закрытие главной формы
Action:=caFree;
//закрытие приложения
218
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Application.Terminate;
end
//если нажата кнопка No
else
//отмена закрытия главной формы
Action :=caNone;
end;
//процедура, вызываемая при уничтожении формы
procedure TAddForm.FormDestroy(Sender: TObject);
begin
//выключение сервера
Server:=nil;
//обнуление длины динамического массива
SetLength(ltemszo);
end;
//процедура, вызываемая сигналами, поступающими с таймера
procedure TAddForm.TimenTimer(Sender: TObject);
var
//счетчик цикла
i:integer;
begin
//чтение величины тегов из ОРС-сервера
for i:=o to n-i do
begin
//чтение из сегмента Segment величины и качества связи тега
HR:=ReadOPCGroupltem Vai ue(Segmentzltems[i]. Item Handle,
ltems[i]. Item Value, ltems[i].ltemQuality);
// если прочитали без ошибок
if Succeeded(HR) then
begin
//если величина тега станет меньше o,ooi
if StrToFloat(ltems[i].ltemValue)<o.ooi then
//установка ItemValue в нуль
ltems[i].ltemValue:='o';
//формат величины тега
ltems[i]. Item Value:=FloatToStrF(StrToFloat(ltems[i]. Item Value),
fffixed, 5,3);
end;
end;
end;
end.
219
РАЗРАБОТКА SCADA-СИСТЕМ
Программный код модуля Main
Листинг 2.7
unit Main;
interface
uses
Windows, Messages, Syslltils, Variants, Classes, Graphics,
Controls, Forms,
Dialogs, ExtCtrls, MPlayer;
type
TMainForm = class(TForm)
//тайме pi
Timeri: TTimer;
//медиаплейер для воспроизведения звука при открытии или
//закрытии ворот
MediaPlayeri:TMediaPlayer;
// таймерз
Timer2: TTimer;
//действия при создании формы
procedure FormCreate(Sender: TObject);
//действия при закрытии формы
procedure FormClose(Sender: TObject; var Action: TCIoseAction);
//реакция на сигналы, поступающие с таймера
procedure TimenTimer(Sender: TObject);
//реакция на вращение колеса мыши вверх
procedure FormMouseWheelUp(Sender: TObject; Shift: TShiftState;
MousePos:TPoint; var Handled: Boolean);
//реакция на вращение колеса мыши вниз
procedure FormMouseWheelDown(Sender:TObject; Shift:TShiftState;
MousePos:TPoint; var Handled: Boolean);
//реакция на сигналы, поступающие с таймера
procedure Timer2Timer(Sender: TObject);
//реакция на нажатие клавиш
procedure FormKeyPress(Sender: TObject; var Key: Char);
private
{Private declarations}
public
{Public declarations}
end;
220
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//создание динамического массива и переменных типа TBitmap
//для хранения графических образов
procedure InitGraph;
//отрисовка графики (ворот)
procedure Graph(Prozent:integer);
const
//количество облаков
obl=io;
var
//главная форма
MainForm: TMain Form;
//объект, на котором отрисовывается изображение (холст)
Bkgrnd:Tlmage;
//переменные для хранения графических образов фрагментов
//забора (центр, левая и правая части)
ZbrCenterzZbrLeftzZbrRight:TBitmap;
//переменная для хранения графического образа ворот
Gate:TBitmap;
//переменная для хранения графического образа скелета
SceletomTBitmap;
//переменные для хранения графических образов фона и облака
BackzCloud:TBitmap;
//длина ворот, левого забора и правого забора
Center, Left, Right:integer;
//масштаб отрисовка изображения:
Ц1 — малый; 2 — средний; 3 — большой
scale:byte;
//переменные для считывания величины тега из ОРС-сервера
dt,olddt:real;
//динамический массив, в котором хранятся координаты
//и шаг перемещения облаков
oo:array of record
//координаты
x,y:integer;
// шаг перемещения облака
s:integer;
end;
implementation
{$R *.dfm}
uses AddUnit;
221
РАЗРАБОТКА SCADA-СИСТЕМ
//действия при создании формы
procedure TMainForm.FormCreate(Sender: TObject);
begin
//инициализация генератора случайных чисел
randomize;
//выключение Timeri
Timen. Enabled :=false;
//интервал таймера Timeri
Ti men. Interval:=10;
//выключение Timeri
Timerz. Enabled :=false;
//интервал таймера Timeri
Timerz. Interval 1=500;
// заголовок формы
Main Form.Caption :='Gate To Happiness1;
//абсцисса левого верхнего угла формы
MainForm. Left:=о;
//ордината левого верхнего угла формы
MainForm.Top:=o;
//ширина формы
Main Form .Width :=Monitor.Width;
//высота формы
Main Form. Height:=Monitor. Height;
//стиль границы формы
Main Form. BorderStyle:=bsNone;
// цвет фона
background:=RG 6(100,150,200);
// цвет формы
Main Form.Color:=background;
//невидимость:
MediaPlayen.Visible:=false;
//имя файла, содержащего скрип открываемых ворот
MediaPlayeri.FileName:='Sound\Gate.wav';
//создание поверхности для рисования графики
Bkgrnd:=Tlmage.Create(Self);
//родитель компонента
Bkgrnd.Parent:=MainForm;
//абсцисса левого верхнего угла компонента
Bkgrnd.Left:=o;
//ордината левого верхнего угла компонента
Bkgrnd.Top:=o;
//ширина компонента
222
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Bkgrnd .Width :=Main Form .Width;
//высота компонента
Bkgrnd. Height:=Main Form. ClientHeight;
//авторазмер запрещен
Bkgrnd. AutoSize:=false;
//автомасштабирование разрешено
Bkgrnd.Stretch :=true;
end;
//создание динамического массива облаков и переменных типа
//TBitmap для хранения графических образов
procedure InitGraph;
var
//счетчик цикла
i:integer;
begin
//начальное значение масштаба отрисовка графики
scale:=i;
//длина динамического массива
SetLength(oozobl);
//создание битового образа центрального фрагмента забора
ZbrCenter:=TBitmap. Create;
//создание битового образа правого фрагмента забора
ZbrRight:=TBitmap.Create;
//создание битового образа левого фрагмента забора
Zbrl_eft:=TBitmap. Create;
//создание битового образа ворот
Gate:=TBitmap. Create;
//создание битового образа скелета, расположенного
//за воротами
Sceleton :=TBitmap.Create;
//создание битового образа фона (пагода и пейзаж вокруг нее)
Baclc=TBitmap. Create;
//загрузка картинки из файла
Back.LoadFromFileCPictures\China.bmp1);
//создание битового образа облака
Cloud:=TBitmap. Create;
//загрузка картинки из файла
Cloud.LoadFromFileCPictures\Cloud.bmp1);
//прозрачность облака разрешена
Cloud. Transparent:=true;
//заполнение динамического массива облаков (obi = ю)
223
РАЗРАБОТКА SCADA-СИСТЕМ
for i:=o to obl-i do
begin
//координата i-го облака no оси x
oo[i].x:=random(Back.Width)-Cloud.Width;
//координата i-го облака no оси у
oo[i].y:=random(2oo);
// шаг перемещения
oo[i].s:=random(3)+i;
end;
//открытие файла с именем MediaPlayen.FileName
Main Form. MediaPlayen. Open;
//включение таймера Timen
Main Form .Timen. Enabled :=true;
//включение таймера Timen
Main Form .Timen. Enabled :=true;
//считывание величины тега
olddt:=StrToFloat(ltems[o]. Item Value);
end;
//закрытие формы
procedure TMainForm.FormClose(Sender: TObject; var Action:
TCIoseAction);
begin
//Timen выключен
Timen. Enabled :=false;
//Timen выключен
Timen. Enabled :=false;
//уничтожение графического образа части забора
ZbrCenter.Free;
//уничтожение графического образа части забора
ZbrLeft.Free;
//уничтожение графического образа части забора
ZbrRight.Free;
//уничтожение графического образа ворот
Gate.Free;
//уничтожение графического образа скелета
Sceleton.Free;
//уничтожение графического образа фона
Back.Free;
//уничтожение графического образа облака
Cloud.Free;
//обнуление длины динамического массива облаков
224
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
SetLength(oozo);
//закрытие файла с именем MediaPlayen.FileName
MediaPlayen.Close;
end;
//отрисовка графики
procedure Graph(Prozent: integer);
var
//ширина и высота элемента забора
zwzzh:integer;
//счетчик цикла
i:integer;
begin
//выбор масштаба отрисовка графики
case scale of
1:
begin
//загрузка картинки из файла
ZbrCenter.LoadFromFileCPictures\Zi\Zi_Center_Low.bmp1);
//загрузка картинки из файла
ZbrLeft.LoadFromFileCPictures\Zi\Zi_Left_Low.bmp1);
//загрузка картинки из файла
ZbrRight.LoadFromFileCPictures\Zi\Zi_Right_Low.bmp1);
//загрузка картинки из файла
Gate.LoadFromFileCPictures\Gatei\Gatei_Low.bmp1);
//загрузка картинки из файла
Sceleton.LoadFromFileCPictures\Sceleton\Sceleton_Low.bmp1);
//ширина ворот
Center:=i2O;
//длина левой части забора
Left:=(Back.Width-Center) div 2;
//длина правой части забора
Right:=(Back.Width-Center) div 2;
end;
2:
begin
//загрузка картинки из файла
ZbrCenter. Load From File ('Pictures\Zi\Zi_Center_Average.bmp');
//загрузка картинки из файла
ZbrLeft.LoadFromFileCPictures\Zi\Zi_Left_Average.bmp1);
//загрузка картинки из файла
ZbrRight. Load From FileCPictures\Zi\Zi_Right_Average.bmp1);
225
РАЗРАБОТКА SCADA-СИСТЕМ
//загрузка картинки из файла
Gate. Load From File('Pictures\Gatei\Gatei_Average.bmp1);
//загрузка картинки из файла
Sceleton.LoadFromFileCPicturesySceletorASceletorcAverage.bmp1);
//расстояние между левой и правой частью забора
Center:=28o;
//длина левой части забора
Left:=(Васк.Width-Center) div 2;
//длина правой части забора
Right:=(Back.Width-Center) div 2;
end;
3:
begin
//загрузка картинки из файла
ZbrCenter.LoadFromFileCPictures\Zi\Zi_Center_High.bmp1);
//загрузка картинки из файла
ZbrLeft.LoadFromFileCPictures\Zi\Zi_Left_High.bmp1);
//загрузка картинки из файла
ZbrRight.LoadFromFileCPictures\Zi\Zi_Right_High.bmp1);
//загрузка картинки из файла
Gate.LoadFromFileCPictures\Gatei\Gatei_High.bmp1);
//загрузка картинки из файла
Sceleton.LoadFromFileCPictures\Sceleton\Sceleton_High.bmp1);
//расстояние между левой и правой частью забора
Center:=42O;
//длина левой части забора
Left:=(Васк.Width-Center) div 2;
//длина правой части забора
Right:=(Back.Width-Center) div 2;
end;
end;
//ширина центрального элемента забора
zw:=ZbrCenter.Width;
//высота центрального элемента забора
zh:=ZbrCenter. Height;
//прозрачность компонента
ZbrCenter.Transparent:=true;
//прозрачность компонента
ZbrLeft.Transparent:=true;
//прозрачность компонента
ZbrRight.Transparent:=true;
//прозрачность компонента
Gate.Transparent:=true;
226
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//прозрачность компонента
Sceleton. Transparent:=true;
//отрисовка скелета
Bkgrnd.Canvas.Draw(Left+Sceleton.Width div 2Z
Back.Height- Sceleton. HeightzSceleton);
//отрисовка ворот
Bkgrnd.Canvas. Draw(Left-round(Gate.Width*Prozent/ioo)-5z
Back. Height-Gate. HeightzGate);
//отрисовка левой части забора
for i:=(l_eft div zw) downto о do
//если отрисовывается последний фрагмент левой части забора
if i=(l_eft div zw) then
//отрисовка правого фрагмента забора
Bkgrnd. Canvas. Draw(i*zwz Back. Height-zhzZbrRight)
else
//отрисовка центрального фрагмента забора
Bkgrnd.Canvas. Draw(i*zwz Back. Height-zhzZbrCenter);
//отрисовка правой части забора
for i:=o to (Right div zw) do
//если отрисовывается первый фрагмент правой части забора
if i=o then
//отрисовка левого фрагмента забора
Bkgrnd. Canvas. Draw(Left+Center+i*zwz Back. Height-zhzZbrLeft)
else
//отрисовка центрального фрагмента забора
Bkgrnd.Canvas. Draw(Left+Center+i*zwz Back. Height-zhzZbrCenter);
end;
//процедура, обслуживающая сигналы, поступающие
//с таймера Timeri
procedure TMainForm.TimenTimer(Sender: TObject);
var
//переменная для считывания тега
dat:integer;
// счетчик цикла
kinteger;
//степень открытости ворот в процентах:
Цо — закрыты; юо — открыты
pnreal;
begin
//выбор из массива величины тега
dat:=round(StrToFloat(ltems[o]. ItemValue));
227
РАЗРАБОТКА SCADA-СИСТЕМ
//вычисление процента открытости ворот
//в расчете на 9000 точек, величина принимается с датчика
//перемещения ворот при их закрытии ипи открытии
pr:=dat*ioo/9ooo;
//отрисовка фона
Bkgrnd. Canvas. Draw(ozoz Back);
//отрисовка облаков
for i:=o to obl-i do
begin
//отрисовка облака
Bkgrnd.Canvas. Draw(oo[i].xzoo[i].yzCloud);
//вычисление координаты no оси x
oo[i].x:=oo[i].x+oo[i].s;
//если облако ушло за границу формы
if oo[i].x>Back.Width then
begin
//вычисление координаты по оси х (облако летит слева
// направо)
oo[i].x:=-Cloud.Width;
//вычисление координаты по оси у
oo[i].y:=random(i2o);
//вычисление шага перемешения
oo[i].s:=random(3)+i;
end;
end;
//отрисовка графики
Graph(round(pr));
end;
//процедура, обслуживающая поворот колеса мыши вверх
// и увеличивающая масштаб изображения графики
procedure TMainForm.FormMouseWheelUp(Sender: TObject;
Shift: TShiftState; MousePos:TPoint; var Handled: Boolean);
begin
//увеличение переменной на единицу
inc(scale);
// если scale=4
if scale>=4 then
//режим от рисовки графики
scale:=3;
case scale of
//заголовок формы
i: MainForm.Caption:='GateTo Happiness: Low Gate1;
228
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//заголовок формы
2: MainForm.Caption:='GateTo Happiness: Average Gate1;
//заголовок формы
3: MainForm.Caption:='GateTo Happiness: High Gate1;
end;
end;
//процедура, обслуживающая поворот колеса мыши вниз
// и уменьшающая масштаб отображения графики
procedure TMainForm.FormMouseWheelDown(Sender:
TObject; Shift: TShiftState; MousePos: TPoint; var Handled:
Boolean);
begin
//уменьшение переменной на единицу
Dec(scale);
if scale<=othen
//режим от рисовки графики
scaled-
case scale of
//заголовки формы
i: MainForm.Caption:='GateTo Happiness: Low Gate1;
2: MainForm.Caption:='GateTo Happiness: Average Gate1;
3: MainForm.Caption:='GateTo Happiness: High Gate1;
end;
end;
//обслуживание сигналов, поступающих с таймера Timeri
procedure TMainForm.Timer2Timer(Sender: TObject);
begin
//считывание величины тега
dt:=StrToFloat(ltems[o]. ItemValue);
// если указатель находится в начале или конце файла
if (MediaPlayen.Position=MediaPlayen.Length) or (MediaPlayen.
Positions) then
//проигрывание файла с именем MediaPlayen. File Name
MediaPlayen.Play;
// если разница между значением тега
Ци его старым значением меньше или равно 2
if abs(dt-olddt)<=2 then
begin
//остановка проигрывания файла
MediaPlayen.Stop;
//указатель в начало файла
229
РАЗРАБОТКА SCADA-СИСТЕМ
MediaPlayeri.Position:=o;
end;
//старое значение тега
olddt:=dt;
end;
//обслуживание нажатий клавиш на клавиатуре
procedureTMainForm.FormKeyPress(Sender:TObject; var Key: Char);
begin
// если была нажата клавиша Esc
if key=#27then
//закрытие формы
MainForm.Close;
end;
end.
2.7. Сетевой лазерный тир
Концепция
Проверить свою меткость и качество огнестрельного оружия
можно и без использования пуль, пороха, патронов. Роль пули мо-
жет играть, например, лазерный луч, выпущенный из обыкновенной
лазерной указки. Тогда роль мишени должна выполнять система, со-
стоящая из светочувствительных элементов, например, фотодиодов.
Расположение фотодиодов в мишени приведено на рис. 2.39.
1 см
1 см
Рис. 2.39. Расположение фотодиодов в мишени
230
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Естественно, что лазерная указка должна быть встроена в не-
что, напоминающее оружие, например, пистолет с курком и прице-
лом (мушкой).
Фотодиоды же должны быть сгруппированы таким обра-
зом, чтобы узкий лазерный луч, попав в активную часть мише-
ни, «засвечивал» хотя бы один фотодиод. В противном случае
удачный выстрел остался бы не замеченным, что не является
удовлетворительным. Мишень должна быть удобной, компакт-
ной, легко переносимой. Электрическое питание схемы мише-
ни целесообразно организовать, используя аккумуляторы, что
делает ее «электрически независимой» от сети переменного
тока.
Требования, предъявляемые к системе управления тиром
1. Четкое определение места попадания луча в мишень.
2. Вывод на экран информации о результативности выстрела
в графической форме, в виде текстового комментария и чис-
ла очков за выстрел.
3. Вывод на экран результатов стрельбы (несколько выстре-
лов) в графической форме, в виде суммарного числа очков
и текстового комментария.
4. Выбор типа звука выстрела.
5. Выбор музыкального сопровождения.
6. Выбор одного из двух режимов стрельбы:
- с произвольным темпом стрельбы и заданным числом
выстрелов,
- с заданным интервалом времени между выстрелами.
7. Введение архива стрельб с возможностью распечатки ин-
формации об их результативности.
Реализация системы управления
Поскольку между компьютером, занимающимся интел-
лектуальной обработкой информации, поступающей с мише-
ни, и мишенью предполагаются большие расстояния (10-200 м),
то вполне обоснованной является реализация системы в виде
КРСУ.
231
РАЗРАБОТКА SCADA-СИСТЕМ
В состав КРСУ будут входить (рис. 2.40):
- контроллер ADAM-5510, образующий нижний уровень
системы управления и реализующий алгоритмы приема
информации с мишени, ее очистку от помех, временную
нормализацию сигналов и передачу информации на верх-
ний уровень системы;
- сервер (мастер сети), образующий верхний уровень систе-
мы управления и реализующий алгоритмы приема инфор-
мации с нижнего уровня их визуализации, архивирования,
воспроизведения архива, передачи этой информации на
другие рабочие станции сети Ethernet.
Программное обеспечение мастера сети будет состоять из трех
компонентов.
1. Fastwel PLCNet ОРС Server — программа, предназна-
ченная для считывания данных с контроллера (контролле-
ров) сети. Через ОРС-сервер пользовательская программа,
ОРС-клиент, реализованная в среде Delphi, примет эти дан-
ные и организует их визуализацию, архивирование, обра-
ботку и т.д.
2. Объект (сервер) автоматизации — это тоже пользователь-
ское приложение, предназначенное для передачи данных
с рабочей станции — мастера по сети Ethernet на другие
рабочие станции. Здесь объект автоматизации рассматри-
ваться не будет, поскольку ОРС-клиент расположен на этом
компьютере.
3. ОРС-клиент, пользовательская программа, которая при-
нимает информацию с контроллера через ОРС-сервер и
организует ее логическую и математическую обработку,
т. е. выполняет функции SCADA-системы.
На рис. 2.41 приведен внешний вид мишени, а на рис. 2.42 —
тот же внешний вид в момент попадания лазерного луча. Хорошо
видны оптические датчики-фотодиоды. Слева виден разъем под-
ключения мишени к контроллеру.
232
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
10-20 метров
Преобразователь
интерфейсов
ADAM-4520
RS-485 RS-232
Рабочая станция N
Fastwel
PLCNet
ОРС Server
Сервер
Автоматизации
(Automation
Object)
Клиент 1
(ОРС Client)
Рабочая станция 1 (мастер)
Рис. 2.40. Состав КРСУ
Рис. 2.41. Внешний вид мишени
233
РАЗРАБОТКА SCADA-СИСТЕМ
Рис. 2.42. Вид мишени в момент попадания лазерного луча
На рис. 2.43 показан момент выстрела. Слева виден монитор
компьютера, на котором в UltraLogik была разработана программа
контроллера, обсуживающего мишень. Вверху виден контроллер,
соединенный кабелем с мишенью. Этот же контроллер витой парой
соединен с компьютером — мастером сети.
На рис. 2.44 справа от мишени виден компьютер — мастер сети
со SCADA-системой, обслуживающей тир. Ее описание приведено
ниже.
Рис. 2.43. Момент выстрела
234
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Рис. 2.44. Мишень и компьютер — мастер сети со SCADA-системой
Мишень и контроллер могут отстоять от мастера на значитель-
ное расстояние (десятки метров), что требуется для работы тира.
На рис. 2.45 приведен весь аппаратный комплекс компьютер-
ного тира:
- контроллер;
- мишень;
- блок питания контроллера.
На мониторе компьютера, на котором составлялась программа
в UltraLogik, видно ее графическое изображение.
На рис. 2.46 приведен внешний вид формы приложения, реали-
зующего SCADA-систему. Текущий выстрел фиксируется на рисун-
ке в центре формы. Суммарные результаты всей серии выстрелов
фиксируются на рисунке в правой части формы. Имеется возмож-
ность:
- просматривать в графической форме и виде текстового опи-
сания результаты всех выстрелов с самого начала;
- очищать экран и базу данных с целью подготовки для новой
серии выстрелов;
- выводить результаты стрельб на принтер;
- задавать музыкальное сопровождение или отключать его;
- выбирать режим работы:
235
РАЗРАБОТКА SCADA-СИСТЕМ
• режим 1, когда выполняется серия с заданным числом
выстрелов с произвольным темпом стрельбы;
• режим 2, когда выполняется серия с заданным коли-
чеством выстрелов и с заданным интервалом между
выстрелами; выстрел производиться после вывода на
колонки (в наушники) звукового предупреждения.
Рис. 2.45. Аппаратный комплекс компьютерного тира
Рис. 2.46. Внешний вид приложения, реализующего SCADA-систему
236
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Программное обеспечение нижнего уровня
Как уже отмечалось выше, программирование нижнего уров-
ня системы выполняется в среде UltraLogik. Рассмотрим, как бу-
дут осуществляться процессы приема и хранения информации,
поступающей с оптических датчиков мишени, а так же процессы
передачи этой информации в компьютер — мастер сети с целью ее
визуализации, обработки и архивирования.
Необходимо отметить, что контроллер должен выполнить сле-
дующую работу:
- принять информацию с 32 оптических датчиков;
- отфильтровать принятые сигналы от помех;
- сформировать информацию о состоянии оптических дат-
чиков и сохранять ее значение до считывания ее по сети
ОРС-сервером, расположенном в компьютере — мастере
сети;
- через некоторое время «обнулить» всю информацию, при-
нятую с оптических датчиков, с целью подготовки к при-
нятию с них новой информации о результатах следующего
выстрела.
Таким образом, можно говорить о следующих переменных:
- переменные vxodl...vxod32 типа Integer, которые пред-
ставляют собой отфильтрованные и нормированные по
времени значения, описывающие состояния 32 оптических
датчиков;
- переменные Т1...Т32 типа Timer, каждая их которых пред-
назначена для временного нормирования информации, по-
ступившей с соответствующего оптического датчика;
- переменные vxl...vx32 типа Boolean, которые отражают
состояние 32 оптических датчиков мишени до их фильтра-
ции и временного нормирования; эти переменные находят-
ся на вкладке Входные, что означает их непосредственную
связь с выходами датчиков и входами модулей ввода инфор-
мации контроллера.
Поскольку в данной работе рассматривается организация про-
граммного обеспечения верхнего уровня КРСУ, то ограничимся
этой информацией.
237
РАЗРАБОТКА SCADA-СИСТЕМ
Программное обеспечение верхнего уровня КРСУ
лазерного тира
ОРС-клиент — SCADA-система — каждые 0,5 секунды опра-
шивает ОРС-сервер Fastwel PLCNet ОРС Server. Получив инфор-
мацию о том, что один из фотодатчиков засвечен, SCADA выпол-
няет следующие действия:
- формирует звук выстрела;
- определяет номер засвеченного фотодатчика;
- выводит изображение мишени с отверстием в месте попа-
дания;
- ОРС-клиент на 1 секунду прекращает опрашивать ОРС-
сервер, давая стрелку подготовиться для нового выстрела;
- ведет архив и т. д.
Приложение, реализующее SCADA-систему, содержит две
формы: AddForm и MainForm. Первая — AddForm (рис. 2.47),
предназначена для:
- ввода имени ОРС-сервера;
- ввода имени сегмента сети;
- ввода в 16-ричной системе номера узла (контроллера);
- ввода имен 32 тегов-сигналов с оптических датчиков;
- ввода координат расположения датчиков; координаты за-
даются по осям X и Y в процентах относительно крайнего
положения;
- ввода количества баллов, которые начисляются в случае,
если в момент выстрела будет засвечен данный оптический
датчик;
- ввода числа используемых каналов (их 32);
- запуска ОРС-сервера (кнопка «Сервер»);
- перехода к основной форме MainForm (кнопка ОК).
238
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Рис. 2.47. Форма AddForm
Компоненты, расположенные на форме AddForm, показаны
на рис. 2.48.
Панель Окно Srv ввода
Panel 1 имени ОРС-сервера
Окно Sgt ввода Окно Node ввода
имени сегмента имени узла
Таблица
Itms для
ввода
тегов
Переключатель \
Snd для
включения или
выключения звука
Кнопка Srvr
запуска ОРС-
сервера
Кнопка
ОК вызова
главной
формы
Логотип Logo
Окно Number
ввода числа тегов
Панель Рапе12
Рис. 2.48. Компоненты формы AddForm
239
РАЗРАБОТКА SCADA-СИСТЕМ
Программный код модуля AddUnit с необходимыми коммента-
риями приведен в листинге 2.8.
Листинг 2.8
unit AddUnit;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics,
Controls, Forms,
Dialogs, ExtCtrls, StdCtrls, Grids, CheckLst, OPCDA, OPCTypes,
OPCUtils, ComObj, ActiveX,
DB, DBCIient, MConnect, SConnect;
type
TAddForm = class(TForm)
Timen: TTimer;
procedure FormCreate(Sender: TObject);
procedure NumberKeyPress(Sender: TObject; var Key:Char);
procedure NumberChange(Sender:TObject);
procedure SrvrClick(Sender:TObject);
procedure OKCIick(Sender:TObject);
procedure FormClose(Sender: TObject; var Action: TCIoseAction);
procedure FormDestroy(Sender: TObject);
procedure TimenTimer(Sender: TObject);
procedure ltmsKeyPress(Sender: TObject; var Key: Char);
private
{Private declarations}
public
{Public declarations}
end;
var
//форма настройки
AddForm: TAddForm;
//цвет фона
background:TColor;
//панели
Paneli, Panel 2:TPanel;
240
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//кнопки ОК и «Сервер»
OKzSrvr:TButton;
//логотип
Logo:Tlmage;
//компоненты для ввода имен сервера, сегмента и узла
SrvzSgtz Node:TLabeled Edit;
//компонент для ввода числа каналов
NumbenTLabeledEdit;
//таблица для ввода имен тегов
ltms:TStringGrid;
//переменная, которая хранит результат операции
HR:HRESULT;
//интерфейс, с помощью которого осуществляется
//добавление тегов в сегмент и их удаление
Segment: lOPCItemMgt;
//включение и выключение звука
Snd:TCheckBox;
//хэндл сегмента
SegmentHandle:OPCHANDLE;
//количество тегов
ndnteger;
//переменная для связи с ОРС-сервером на одном
//компьютере
ServerdOPCServer;
//массив тегов
ltems:array of record
//название тега
ltemName:string;
//хэндл тега
ltemHandle:OPCHANDLE;
//тип тега
ItemTypeiTVarType;
//величина тега
ltemValue:string;
//качество связи тега
ltemQuality:word;
end;
//массив точек попадания.
//точка попадания — это круг, находящийся
// в прямоугольнике. Прямоугольник имеет размеры:
//ширина равна Canvas.Width /8,
//высота равна Canvas.Height/8.
241
РАЗРАБОТКА SCADA-СИСТЕМ
//диаметр круга равен (Canvas.Width(Height) / 8)*о,5
//прямоугольник и круг имеют общий центр
krckarray of record
//координаты центра точки попадания в процентах.
//имеется поле попадания: 8x8 точек.
// для работы используется поле 7x7 точек.
// поскольку мишень с центром,
//должна иметь нечетное число точек попадания.
//минимальное расстояние между двумя точками
//по оси хиуравно юо °/о/8 = 125 %.
//здесь юо °/о — это ширина или высота всего поля Canvas
//например, точка с координатами (50,50)
// будет находиться в центре мишени,
// а точка (12.5,12.5) в левом верхнем углу мишени.
//диапазон координат центра точек попадания
// от 12,5 до 87,5 °/о с шагом 12,5 °/о
x,y:real;
//признак попадания в точку: о или 1
z:byte;
// число очков за попадание в эту точку
points:integer;
// число попаданий в точку
minteger;
end;
implementation
uses Main;
{$R *.dfm}
//процедура no созданию формы настройки
procedure TAddForm.FormCreate(Sender: TObject);
var
//счетчик цикла
i:integer;
//переменная для вычисления какой-либо величины
pnreal;
//файловая переменная
f:TextFile;
//переменная, в которую считываются строки из файла
s:string;
begin
242
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//начальное значение
Segment:=nil;
//начальное значение
Server:=nil;
//запрещение работы таймера Timen
Timeri. Enabled :=false;
//интервал работы таймера
Timeri. Interval :=юо;
//число каналов по умолчанию
п:=8;
//установка длины динамического массива переменных в п
SetLength(ltemszn);
//заполнение динамического массива переменных нулями
for i:=o to n-i do
ltems[i]. Item Vai ue:='o';
//настройки дополнительной формы
// цвет фона
background:=RG 6(100,150,200);
pr-50;
//ширина компонента
Add Form .Width :=round((Monitor.Width/ioo)*pr);
pr:=43;
//высота компонента
Add Form. Height:=round((Monitor.Height/ioo)*pr);
//позиция дополнительной формы на дисплее
Add Form. Position :=poScreenCenter;
//заголовок дополнительной формы
Add Form.Caption :='Настройка ОРС-сервера1;
//стиль границ дополнительной формы
Add Form. BorderStyle:=bsSingle;
//разрешенные иконки на дополнительной форме
Add Form. Borderlcons:=[biSystem Menu];
//цвет дополнительной формы
Add Form. Color:=background;
//создание панели, на которой расположены компоненты,
//обеспечивающие ввода имен сервера, сегмента и узла
//создание компонента
Paneli:=TPanel.Create(Self);
//родитель компонента
Paneli. Parent:=Add Form;
рг:=1;
//ордината левого верхнего угла компонента
243
РАЗРАБОТКА SCADA-СИСТЕМ
Paneli.Top:=round((Monitor.Height/ioo)*pr);
pr-0.5;
//абсцисса левого верхнего угла компонента
Paneli. Left:=round((Monitor.Width/ioo)*pr);
рг-48.5;
//ширина компонента
Paneli.Width :=round((Monitor.Width/ioo)*pr);
рг:=8;
//высота компонента
Paneli. Height:=round((Monitor.Height/ioo)*pr);
//стиль внутренней границы компонента
Paneli. Bevel lnner:=bvRaised;
//стиль внешней границы компонента
Paneli. BevelOuter:=bvl_owered;
//цвет компонента
Paneli. Color:=background;
//создание компонента для ввода имени сервера
//создание компонента
Srv: =TLabeled Ed it. Create(Self);
//родитель компонента
Srv.Parent:=Paneli;
рг:=з;
//ордината левого верхнего угла компонента
Srv.Top:=round((Monitor.Height/ioo)*pr);
рг-1.5;
//абсцисса левого верхнего угла компонента
Srv.Left:=round((Monitor.Width/ioo)*pr);
//авторазмер компонента
Srv.AutoSize:=false;
//размер шрифта компонента
Srv.Font.Size:=io;
//цвет компонента
Srv.Color:=clWhite;
рг:=з;
//высота компонента
Srv.Height:=round((Monitor.Height/ioo)*pr);
рг-17;
//ширина компонента
Srv.Width:=round((Monitor.Width/ioo)*pr);
//заголовок компонента
Srv. EditLabel. Caption:='OPC-Server';
//цвет заголовка компонента
244
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Srv.EditLabel. Font. Colored White;
//свойство text компонента
Srv.Text:='Fastwel.PLCNetOPC;
//создание компонента для ввода имени сегмента
//создание компонента
Sgt:=TLabeled Ed it.Create(Self);
//родитель компонента
Sgt.Parent:=Paneli;
pr-з;
//ордината левого верхнего угла компонента
Sgt.Top:=round((Monitor.Height/ioo)*pr);
рг:=2О;
//абсцисса левого верхнего угла компонента
Sgt.Left:=round((Monitor.Width/ioo)*pr);
//авторазмер компонента
Sgt.AutoSize:=false;
//размер шрифта компонента
Sgt. Font. Size:=io;
//цвет компонента
Sgt.Color:=clWhite;
pr-з;
//высота компонента
Sgt.Height:=round((Monitor.Height/ioo)*pr);
рг-17;
//ширина компонента
Sgt. Width :=round((Monitor.Width/ioo)*pr);
//заголовок компонента
Sgt. EditLabel. Caption :='Сегмент UltraNet1;
//цвет заголовка компонента
Sgt. EditLabel. Font.Colored White;
//свойство text компонента
Sgt.Text:='Ultranet_i';
//создание компонента для ввода имени узла
//создание компонента
Node:=TLabeledEdit.Create(Self);
//родитель компонента
Node.Parent:=Paneli;
рг:=з;
//ордината левого верхнего угла компонента
Node.Top:=round((Monitor.Height/ioo)*pr);
рг-38.5;
//абсцисса левого верхнего угла компонента
245
РАЗРАБОТКА SCADA-СИСТЕМ
Node.Left:=round((Monitor.Width/ioo)*pr);
//авторазмер компонента
Node.AutoSize:=false;
//размер шрифта компонента
Node. Font. Size:=io;
//цвет компонента
Node.Colored White;
pr-з;
//высота компонента
Node.Height:=round((Monitor.Height/ioo)*pr);
pr:=8.5;
//ширина компонента
Node.Width :=round((Monitor.Width/ioo)*pr);
//заголовок компонента
Node. EditLabel.Caption :='Узел';
//цвет заголовка компонента
Node. EditLabel. Font.Colored White;
//свойство text компонента
Node.Text-'FE1;
//создание компонента
Panel2:=TPanel.Create(Self);
// родитель компонента
Panel2.Parent:=AddForm;
pr:=io;
//ордината левого верхнего угла компонента
Panel2.Top:=round((Monitor.Height/ioo)*pr);
рг-0.5;
//абсцисса левого верхнего угла компонента
Panel2.Left:=round((Monitor.Width/ioo)*pr);
рг-48.5;
//ширина компонента
Panel2.Width:=round((Monitor.Width/ioo)*pr);
рг-29;
//высота компонента
Panel2.Height:=round((Monitor.Height/ioo)*pr);
//стиль внутренней границы компонента
Panel2.Bevellnner:=bvRaised;
//стиль внешней границы компонента
Panel2.BevelOuter:=bvLowered;
//цвет компонента
Panel2.Color:=background;
//создание компонента
246
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Number:=TLabeledEdit.Create(Self);
//родитель компонента
Number. Parent:=Panel2;
рг-23;
//ордината левого верхнего угла компонента
Number.Top:=round((Monitor.Height/ioo)*pr);
рг:=18;
//абсцисса левого верхнего угла компонента
Number. Left:=round((Monitor.Width/ioo)*pr);
//авторазмер компонента
Number. AutoSize:=false;
//размер шрифта компонента
Number. Font. Size:=io;
//цвет компонента
Number.Color:=cl White;
рг:=з;
//высота компонента
Number. Height:=round((Monitor. Height/ioo)*pr);
рг:=11;
//ширина компонента
Number.Width:=round((Monitor.Width/ioo)*pr);
//заголовок компонента
Number.EditLabel.Caption^'Hi/icno каналов1;
//цвет заголовка компонента
Number. EditLabel. Font.Colored White;
//свойство text компонента
Number.Text:='8';
//событие OnKeyPress компонента
Number.OnKeyPress:=NumberKeyPress;
//событие OnChange компонента
Number.OnChange:=NumberChange;
//создание компонента
ltms:=TStringGrid.Create(Self);
//родитель компонента
ltms.Parent:=Panel2;
pr-0.5;
//абсцисса левого верхнего угла компонента
ltms.Left:=round((Monitor.Width/ioo)*pr);
рг:=1;
//ордината левого верхнего угла компонента
ltms.Top:=round((Monitor.Height/ioo)*pr);
рг:=47-5;
247
РАЗРАБОТКА SCADA-СИСТЕМ
//ширина компонента
ltms.Width:=round((Monitor.Width/ioo)*pr);
рг:=19;
//высота компонента
ltms.Height:=round((Monitor.Height/ioo)*pr);
//цвет компонента
ltms.Color:=clWhite;
//цвет фиксированных строк и столбцов компонента
Itms. Fixed Color:=cl White;
//число столбцов компонента
ltms.ColCount:=n+i;
// число строк компонента
ltms.RowCount:=5;
рг:=8;
//ширина столбцов компонента
Itms. Defaulted Width :=round((Monitor.Width/ioo)*pr);
//заполнение ячеек таблицы
Itms.CellstO/Oj^'Hoiviep1;
Itms.Cel 15[о/п]:='Имя|;
ltms.Cells[o/2]:=,X(%)1;
ltms.Cells[o/3]:=lY(°/o)1;
ltms.Cells[o/4]:=lO4i<nl;
for i:=i to n do
begin
//содержимое ячейки
Itms.Cel 15[1/о]:='Канал '+lntToStr(i);
//содержимое ячейки
Itms. Cel ls[i,i]:Vxod'+1 ntToStr(i);
end;
//настройка опций компонента
ltms.Options:=[goFixedVertLinezgoFixedHorzLinezgoVertLinezgoHorz
LinezgoRangeSelectzgoEditing];
//событие OnKeyPress компонента
ltms.Onl<eyPress:=ltmsl<eyPress;
//создание компонента
Snd:=TChecl<Box.Create(Self);
//родитель компонента
Snd.Parent:=Panel2;
//заголовок компонента
Snd. Са ption: ^'Звук1;
//шрифт компонента
Snd.Font.Size:=8;
248
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//цвет шрифта компонента
Snd. Font. Colored White;
pr-24;
//ордината левого верхнего угла компонента
Snd.Top:=round((Monitor.Height/ioo)*pr);
рг:=12;
//абсцисса левого верхнего угла компонента
Snd.Left:=round((Monitor.Width/ioo)*pr);
рг:=4;
//ширина компонента
Snd. Width :=round((Monitor.Width/ioo)*pr);
//свойство Checked компонента
Snd.Checked:=true;
//создание компонента
Logo:=Tlmage.Create(Self);
//родитель компонента
Logo.Parent:=Panel2;
рг-0.5;
//абсцисса левого верхнего угла компонента
Logo.Left:=round((Monitor.Width/ioo)*pr);
рг:=21;
//ордината левого верхнего угла компонента
Logo.Top:=round((Monitor.Height/ioo)*pr);
рг:=ю;
//ширина компонента
Logo.Width :=round((Monitor.Width/ioo)*pr);
рг:=7;
//высота компонента
Logo.Height:=round((Monitor.Height/ioo)*pr);
//загрузка картинки из файла
Logo. Picture. Load From File('AM.bmp');
//создание компонента
Srvr:=TButton.Create(Srvr);
//родитель компонента
Srvr.Parent:=Panel2;
//заголовок компонента
Srvr.Caption:='CepBep';
pr-32;
//абсцисса левого верхнего угла компонента
Srvr.Left:=round((Monitor.Width/ioo)*pr);
рг-23;
//ордината левого верхнего угла компонента
249
РАЗРАБОТКА SCADA-СИСТЕМ
Srvr.Top:=round((Monitor.Height/ioo)*pr);
pr:=6;
//ширина компонента
Srvr.Width:=round((Monitor.Width/ioo)*pr);
Рг:=3-5;
//высота компонента
Srvr.Height:=round((Monitor.Height/ioo)*pr);
//событие OnClickкомпонента
Srvr.OnCI ick:=SrvrCI ick;
//создание компонента
OK:=TButton.Create(Self);
//родитель компонента
OK.Parent:=Panel2;
//заголовок компонента
OK.Caption-'OK1;
pr:=zpL;
//абсцисса левого верхнего угла компонента
OK.Left:=round((Monitor.Width/ioo)*pr);
рг-23;
//ордината левого верхнего угла компонента
OK.Top:=round((Monitor.Height/ioo)*pr);
рг:=6;
//ширина компонента
OK.Width:=round((Monitor.Width/ioo)*pr);
РГ:=3-5;
//высота компонента
OK.Height:=round((Monitor.Height/ioo)*pr);
//событие OnClickкомпонента
OK.OnClick:=OKCIick;
//поиск файла
if FileExists('AutoSave.sav') then
// если файл существует, то
begin
// связь файловой переменной с файлом
AssignFile(f, 'AutoSave, sav1);
//открытие файла для чтения
Reset(f);
//чтение имени сервера
readln(f,s);
//свойство text компонента
Srv.Text:=s;
//чтение имени сегмента
250
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
readings);
//свойство text компонента
Sgt.Text:=s;
//чтение имени узла
readings);
//свойство text компонента
Node.Text:=s;
//чтение числа каналов
readings);
//свойство text компонента
Number.Text:=s;
//если свойство text состоит из нуля символов
if Number.Text=" then
// число каналов
П:=О
else
// число каналов
n:=StrTolnt(Number.Text);
//установка длины динамического массива
SetLength(ltemszn);
// если число каналов не равно нулю, то
if noo then
//цикл по п каналам
for i:=o to n-i do
//начальное значение величины тега
ltems[i]. Item Vai ue:='o';
//число столбцов в таблице
ltms.ColCount:=n+i;
// если число каналов не равно нулю
if noo then
begin
// число фиксированных столбцов в таблице
ltms.FixedCols:=i;
//цикл по п каналам
for i:=i to n do
begin
//содержимое ячейки
Кт5.Се115[1/о]:='Канал '+lntToStr(i);
//содержимое ячейки
Itms.Cel ls[izi]:='Vxod'+lntToStr(i);
end;
end;
251
РАЗРАБОТКА SCADA-СИСТЕМ
//чтение имен тегов
for i:=o to n-i do
begin
//чтение имени тега
readings);
//содержимое ячейки
Itms. Cel I s[i+izi]:=s;
end;
//чтение координат точки no оси x
for i:=o to n-i do
begin
//чтение координаты точки no оси x
readings);
//содержимое ячейки
ltms.Cells[i+i/2]:=s;
end;
//чтение координат точки по оси у
for i:=o to n-i do
begin
//чтение координаты точки no оси у
readings);
//содержимое ячейки
ltms.Cells[i+i/3]:=s;
end;
//чтение количества очков, начисляющихся за попадание
// в эту точку
for i:=o to n-i do
begin
//чтение количества очков
readings);
//содержимое ячейки
ltms.Cells[i+i/4]:=s;
end;
//закрытие файла
CloseFile(f);
end;
end;
//происходит при изменении текста в компоненте Number
procedure TAddForm. NumberChange(Sender: TObject);
var
i:integer; // счетчик цикла
252
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
begin
//отключение таймера
Timeri. Enabled :=false;
// если свойство text состоит из нуля символов
if Number.Text=" then
// число каналов
П:=О
else
//число каналов
n:=StrTolnt(Number.Text);
//установка длины динамического массива
SetLength(ltemszn);
// если число каналов не равно нулю
if noo then
//цикл по п каналам
for i:=o to n-i do
//начального значения величины тега
Itemsfi]. Item Va I ие:='о';
//число столбцов в таблице
ltms.ColCount:=n+i;
// если число каналов не равно нулю
if noo then
begin
// число фиксированных столбцов в таблице
ltms.FixedCols:=i;
//цикл по п каналам
for i:=i to n do
begin
//содержимое ячейки
Кт5.Се115[1/о]:='Канал '+lntToStr(i);
//содержимое ячейки
ltms.Cells[i/i]:=lVxodl+lntToStr(i);
end;
end;
end;
//происходит при нажатии клавиши на компоненте Number
procedure TAddForm.NumberKeyPress(Sender:TObject; var Key: Char);
begin
case key of
//разрешенные символы
lol..l9lz#8:
253
РАЗРАБОТКА SCADA-СИСТЕМ
else
//остальные запрещены
кеу:=#о;
end;
end;
//происходит при щелчке мышью по кнопке Srvr
procedure TAddForm.SrvrClick(Sender: TObject);
begin
try
//создание ОРС-сервера
Server:=CreateComObject(ProglDToClasslD(Srv.Text)) as lOPCServer;
//если произошла ошибка
except
//сообщение об ошибке
ShowMessage('He могу запустить сервер!!!1);
//уничтожение сервера
Server:=nil;
end;
end;
//происходит при щелчке мышью по кнопке ОК
procedure TAddForm.OKCIick(Sender: TObject);
var
i:integer; // счетчик цикла
begin
//отключение таймера
Timeri. Enabled :=false;
// если число каналов равно нулю
if n=o then
begin
//сообщение об ошибке
ShowMessage('Heo6xoAHMO добавить хотя бы один тег!!!1);
//выход из процедуры
exit;
end;
//цикл по п каналам
for i:=o to n-i do
// если одна из ячеек пуста
if Itms. Cells[i/2]=" then
//выход из процедуры
exit;
254
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//цикл по п каналам
for i:=o to n-i do
// если одна из ячеек пуста
if Itms. Cel ls[i,3]=" then
//выход из процедуры
exit;
//цикл по п каналам
for i:=o to n-i do
// если одна из ячеек пуста
if Itms. Cel ls[i/zJ.]=" then
// выход из процедуры
exit;
//установка длины динамического массива
SetLength(krd,n);
//цикл по п каналам
for i:=o to n-i do
begin
//координата точки no оси x
krd[i].x:=StrToFloat(ltms.Cells[i+i/2]);
//координата точки no оси у
krd[i].y:=StrToFloat(ltms.Cells[i+i/3]);
//начальное значение
krd[i].z:=o;
//количество очков
krd[i].points:=StrTolnt(ltms.Cells[i+i/zh]);
//число попаданий
krd[i].n:=o;
end;
//уничтожение сервера
Server:=nil;
try
//создание сервера
Server:=CreateComObject(ProglDToClasslD(Srv.Text)) as lOPCServer;
// если не смогли создать сервер
except
//сообщение об ошибке
ShowMessage('He могу запустить сервер!!!1);
//уничтожение сервера
Server:=nil;
//выход из процедуры
Exit;
end;
255
РАЗРАБОТКА SCADA-СИСТЕМ
//если сегмент Ultranet не добавлен
if Segment=nil then
//добавление сегмента в сервер
HR:=ServerAddGroup(Server,Sgt.Text,true,1,о, Segment,
SegmentHandle);
//если произошла ошибка
if Failed(HR) then
begin
//сообщение об ошибке
ShowMessage('He могу добавить сегмент UltraNet!!!1);
//уничтожение сервера
Server:=nil;
//выход из процедуры
Exit;
end;
//добавление тегов в сегмент
for i:=o to n-i do
begin
//полное имя тега
ItemsfiJ. Item Name:=Sgt.Text+'.'+Node.Text+'.'+ltms.Cel ls[i+i,ij;
//если переменной не существует
if ltems[i].ltemHandle=o then
//добавление тега
HR:=GroupAddltem(Segment,ltems[i]. Item Name,SegmentHandle,
VT_EM PTY, ltems[i]. Item Handle, ltems[i].ltemType);
// если произошла ошибка
if Failed(HR) then
begin
//сообщение об ошибке
ShowMessage('He могу добавить переменную
l+ltems[i].ltemName+l !!!');
//уничтожение сервера
Server:=nil;
//выход из процедуры
Exit;
end;
end;
// если флажок сброшен
if not Snd.Checked then
begin
//выбор музыки запрещен
Sei Music. Enabled :=false;
256
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//выбор звуков запрещен
SelSound. Enabled :=false;
//музыка запрещена
NoMusic.Checked :=false;
//включение (выключение) музыки запрещено
NoMusic. Enabled :=false;
end
// если флажок установлен
else
begin
//выбор музыки разрешен
Sei Music. Enabled :=true;
//выбор звуков разрешен
SelSound. Enabled :=true;
//музыка разрешена
NoMusic.Checked :=true;
//включение (выключение) музыки разрешено
NoMusic. Enabled :=true;
//выбор и воспроизведение звукового файла
RandomMusic;
end;
//скрыть форму
AddForm.Hide;
// заголовок формы
Main Form.Caption :=Тир';
// заголовок метки
1_аЬе1з.Сар1юп:='Выстрел: о1;
// заголовок метки
LabelzpCaption^'o из о1;
//отрисовка мишени
lnitTarget(Target. Canvas/Target.WidthJarget. Height);
//отрисовка мишени
InitTargettTotal.CanvaS/Total.WidthJotal. Height);
//имя файла (выстрел из оружия)
Main Form. Weapon. FileName:=path+'\Sound\'+sound[SelSound.
Item Index];
//открытие файла
Main Form .Weapon.Open;
//количество выстрелов
n_shoot:=o;
//количество очков
pnts:=o;
257
РАЗРАБОТКА SCADA-СИСТЕМ
//очистка результатов в ТМето
Result.Clear;
//установка длины динамического массива
SetLength(shoot,n_shoot);
//минимум
UpDown.Min:=o;
//максимум
U р Down. Мах:=о;
//текущая позиция
UpDown. Position :=о;
//приращение
UpDown. Increment:^;
// если выбран второй режим
if Mode. Item Index=i then
begin
// если не указаны количество выстрелов или интервал
if (Shoots.Texto") and (Int.Texto") then
//кнопка Start запрещена
Start. Enabled:=true
else
//кнопка Start разрешена
Start. Enabled:=false;
end;
// вызов главной формы
MainForm.Show;
end;
//происходит при закрытии формы
procedure TAddForm.FormClose(Sender: TObject; var Action:
TCIoseAction);
var
//переменная для хранения выбранного действия
//пользователя
inf: Word;
//файловая переменная
f:TextFile;
//счетчик цикла
i:integer;
begin
//вызов диалогового окна для закрытия формы
inf:=MessageDlg('Вы уверены?1,mtlnformation,[mbYes/mbNo]/o);
// если нажата кнопка Yes
258
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
if inf=mrYes then
begin
И связь файловой переменной с файлом
Assign File(f, 'AutoSave, sav1);
//перезапись файла
Rewrite(f);
//запись имени сервера
write I n(fzSrv.Text);
//запись имени сегмента
writeln(fzSgt.Text);
//запись имени узла
write I n (fz Node.Text);
//запись числа тегов
write ln(fz number, text);
//запись имен тегов
for i:=o to n-i do
//запись имени тега
writeln(f/ltms.Cells[i+i/i]);
//запись координат точки по оси х
for i:=o to n-i do
//запись координаты точки по оси х
writeln(f/ltms.Cells[i+i/2]);
//запись координат точки по оси у
for i:=o to n-i do
//запись координаты точки по оси у
writeln(f/ltms.Cells[i+i/3]);
//запись количества очков
for i:=o to n-i do
//запись количества очков
writeln(f/ltms.Cells[i+i/zh]);
//закрытие файла
CloseFile(f);
// запрещение таймера
Timen. Enabled :=false;
//уничтожение сервера
Server:=nil;
//установка длины динамического массива в нуль
//элементов
SetLength(ltemszo);
//установка длины динамического массива в нуль
//элементов
SetLength(musiczo);
259
РАЗРАБОТКА SCADA-СИСТЕМ
//установка длины динамического массива в нуль элементов
SetLength(sound,o);
//разрешение на закрытие главной формы
Action:=caFree;
//завершение приложения
Application.Terminate;
end
// если нажата кнопка No
else
//отмена закрытия главной формы
Action:=caNone;
end;
//происходит при уничтожении формы
procedure TAddForm.FormDestroy(Sender: TObject);
begin
//уничтожение сервера
Server:=nil;
//установка длины динамического массива
SetLength(ltems,o);
end;
//происходит через определенный интервал времени
procedure TAddForm.TimenTimer(Sender: TObject);
var
//счетчик цикла
i:integer;
begin
//чтение значений тегов из ОРС-сервера
for i:=o to n-i do
begin
// чтение из группы Segment значения и качества связи
//переменной с хэндлом ItemHandle в переменные
//ItemValue и ItemQuality
HR:=ReadOPCGroupltemValue(Segment, ltems[i]. Item Handle, ltems[i].
ItemValue, ltems[i].ItemQuality);
// если прочитали без ошибок
if Succeeded(HR) then
begin
//если тег станет меньше o.ooi
if StrToFloat(ltems[i].ltemValue)<o.ooi then
260
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//ItemValue в нуль
ItemsfiJ. ltemValue:='o';
//округление тега
Itemsfi]. Item Vai ue:=FloatToStrF(StrToFloat(ltems[i]. ItemValue),
fffixed,5,3);
//признак попадания в точку
krdfi].z:=round(StrToFloat(ltems[i]. Item Value));
end;
end;
//проверка динамического массива krd — поиск точки попадания
Check(f);
// если обнаружилось попадание в какую-либо точку
if f then
//задержка на i секунду
sleep(iooo);
end;
//происходит при нажатии клавиши на компоненте Itms
procedureTAddForm.ltmsKeyPress(Sender:TObject; var Key: Char);
var
//переменная для временного хранения содержимого ячейки
ItmsSelTextistring;
begin
//если выделена ячейка во второй или третьей строке
if (Itms. Ro w=2) or (ltms.Row=3) then
begin
//копирование содержимого выделенной ячейки
ltmsSelText:=ltms.Cel ls[ltms.Col, Itms. Row];
case key of
//разрешенные символы
o'./g'^S:;
/ /
begin
//текущий десятичный разделитель
key:=DecimalSeparator;
// если символ уже имеется в ячейке
if pos(key,ltmsSelText)oo then
//отмена добавления символа в ячейку
1<еу:=#о;
end
//остальные символы запрещены
261
РАЗРАБОТКА SCADA-СИСТЕМ
else
кеу:=#о;
end;
end;
//если выделена ячейка в четвертой строке
if ltms.Row=4 then
case key of
//разрешенные символы
oUg'^S:;
//остальные символы запрещены
else
key :=#о;
end;
end;
end.
Данное приложение в начале работы опрашивает текстовый
файл AutoSave.sav и, если он имеется, считывает из него информа-
цию и заполняет таблицу на форме AddForm. Считывание произво-
дится в следующей последовательности:
- имя ОРС-сервера;
- имя сегмента сети;
- номер узла в 16-ричной системе счисления;
- число датчиков и, соответственно, число каналов (би-
тов);
- имена тегов, связанных с оптическими датчиками;
- координаты X всех 32 датчиков, начиная с 1-го и кончая
32-м;
- координаты Y всех 32 датчиков, начиная с 1-го и кончая
32-м;
- очки, начисляемые стрелку в случае засветки датчиков, на-
чиная с 1-го и кончая 32-м.
Ниже приведено начало типичного файла AutoSave.sav. Каж-
дая величина записана в отдельной строке файла. После окон-
чания работы с данным приложением вся информация, заполня-
ющая таблицу формы AddForm, вновь запоминается в файле
AutoSave.sav.
262
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Fastwel. PLCNetOPC
Ultra net_i
FD
32
Vxodi
Vxoch
Vxod3
Vxodzp
Vxods
Vxod6
Vxody
Vxod8
Vxodg
Vxodio
Vxodn
Vxodi2
Vxodi3
Vxodio
Vxodi5
Vxodi6
Vxodiy
Vxodi8
Vxodig
Vxod2o
Vxod2i
Vxod22
Vxod23
Vxod24
Vxod25
Vxod26
Vxod27
Vxod28
Vxod29
Vxod3o
Vxod3i
Vxod32
37,5
50
62,5
25
37,5
263
РАЗРАБОТКА SCADA-СИСТЕМ
Внешний вид формы MainForm показан на рис. 2.49.
Переключатель
NoMusic для включения
С ппсок SelMusic
для выбора
или выключения музыки музыки
Панель Раие12
Выстрел; 24
Музыка
Зчук выстрела
г тг \
Окно Shoots Кнопки Start и
для ввода I Stop — начало
количества 1 и завершение
выстрелов 1 стрельбы
Кнопка
Ext — выход
из
Счетчик UpDown для
просмотра предыдущих
выстрелов
Список SelSoimd /панель радио кнопок
для выбора звука/ у lode для выбора
выстрела у режима стрельбы у
очистка
результатов
Кнопка
Clear —
Кнопка
Prut —
распечатка
результатов
Панель
Panell I
\ I
ft** 2
18 Поводом, cs&pxy 7 ОЧКОВ1Н
19 Слева снизу 9 очксвШ
20 В центр 10 очков11!
21 Посередине, сверху ? о говЩ
22 Справа сверху8 omkcsHI
29 В центр 10
24 Chpata о-мзу 8 очков!!1
194 и з 240
Окно Int для ввода
интервала стрельбы
Окно редактирования Result для
вывода результатов стрельбы
Рис. 2А9. Форма MainForm с пояснениями
Из рис. 2.49 видно, какой сервис представляет SCADA-
система:
- просмотр результата очередного выстрела в графической
форме;
- просмотр результатов всех выстрелов в графической форме;
- просмотр результатов любого предыдущего выстрела
в графической форме;
- включение/выключение музыкального сопровождения;
- выбор музыки для музыкального сопровождения;
264
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
- выбор звука выстрела;
- выбор одного из двух режимов стрельбы;
- задание количества выстрелов для режима 1;
- задание интервала стрельбы для режима 2;
- вывод результатов стрельбы в текстовой форме с коммента-
риями;
- очистка результатов текущей стрельбы перед новой стрель-
бой;
- печать результатов стрельбы;
- запуск и останов стрельбы;
- выход из приложения.
Программный код модуля Main приведен в листинге 2.9.
Листинг 2.9
unit Main;
interface
uses
Windows, Messages, Syslltils, Variants, Classes, Graphics,
Controls, Forms,
Dialogs, ExtCtrls, StdCtrls, MPlayer, CheckLst, ComCtrls;
type
TMainForm = class(TForm)
Msc: TMediaPlayer;
Weapon: TMediaPlayer;
Speech: TMediaPlayer;
Timeri: TTimer;;
Timer2: TTimer;
procedure SelMusicDblClick(Sender: TObject);
procedure SelSoundClick(Sender: TObject);
procedure NoMusicClick(Sender:TObject);
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCIoseAction);
procedure TimenTimer(Sender: TObject);
procedure ClearClick(Sender: TObject);
procedure ExtClick(Sender: TObject);
procedure UpDownClick(Sender: TObject; Button: TUDBtnType);
265
РАЗРАБОТКА SCADA-СИСТЕМ
procedure ModeClick(Sender: TObject);
procedure ShootsKeyPress(Sender: TObject; var Key: Char);
procedure lntKeyPress(Sender: TObject; var Key: Char);
procedure ShootsChange(Sender: TObject);
procedure lntChange(Sender: TObject);
procedure StartClick(Sender: TObject);
procedure StopClick(Sender: TObject);
procedure Timer2Timer(Sender: TObject);
private
{Private declarations}
public
{Public declarations}
end;
//выбирает случайным образом и проигрывает звуковой файл
procedure RandomMusic;
//отрисовывает мишень с размерами wuh на Canvas
procedure lnitTarget(Canvas:TCanvas;w,h integer);
//отрисовывает точку попадания на Canvas
procedure Bullet(Canvas:TCanvas;w,h:integer;s:integer;Digit:boolean);
//проверка динамического массива krd — поиск точки попадания
procedure Check(var found:boolean);
var
//главная форма
MainForm: TMain Form;
//панели
Paneli, Panel 2:TPanel;
//метки
Labeli,Label2:TLabel;
//фон
background integer;
//компоненты для от рисовки на них графических изображений
Target,Total :Tlmage;
//кнопки «Очистка», «Печать» и «Выход»
Clear, Prnt,Ext:TButton;
//кнопки «Старт» и «Стоп»
Start, Stop:TButton;
//компонент для выбора режима стрельбы
Mode:TRadioGroup;
//окна для ввода количества выстрелов и интервала
Shoots, lnt:TLabeled Edit;
//признаки попадания в точку для первого и второго режима
266
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
f,ff:boolean;
//компонент для выбора музыки
SelMusicTListBox;
//компонент для выбора звука стрельбы
SelSound:TComboBox;
//включение и выключение музыки
NoMusicTCheckBox;
//компонент для вывода результатов стрельбы
Result:TMemo;
//компонент для перемотки результатов стрельбы
UpDowmTUpDown;
//метки
Labe^LabelzpTLabel;
//список звуковых файлов (музыка)
musicarray of string;
//список звуковых файлов (звук стрельбы)
sounckarray of string;
//массив для хранения номеров тегов.
//например, если третий элемент массива имеет значение $,
//то это означает, что на третьем выстреле попали в
//точку с номером 5
shoot:array of integer;
//длины динамических массивов music и sound
Imusicjsounckinteger;
//директория приложения
path :string;
//количество выстрелов и очков после последней очистки
n_shoot, pnts:integer;
implementation
uses Add Unit;
{$R *.dfm}
//процедура создания главной формы
procedure TMainForm.FormCreate(Sender: TObject);
var
//переменная для вычисления размеров какого-либо компонента
pnreal;
//счетчик цикла
i:integer;
//переменная для поиска файла Autosave.sav
Search RecTSearch Rec;
267
РАЗРАБОТКА SCADA-СИСТЕМ
begin
//инициализация генератора случайных чисел
randomize;
//компонент Msc(TMediaPlayer) невидим
М sc.Visi Ые: =fa Ise;
// тип устройства
Msc.DeviceType:=dtAutoSelect;
//компонент Weapon(TMediaPlayer) невидим
Weapon. Visible:=false;
//тип устройства
Weapon. DeviceType:=dtAutoSelect;
//компонент Speech(TMediaPlayer) невидим
Speech. Visible:=false;
// тип устройства
Speech. DeviceType:=dtAutoSelect;
//запрещение работы таймера
Timeri. Enabled :=false;
//интервал работы таймера
Timeri. Interval:=юоо;
//запрещение работы таймера
Timer2.Enabled:=false;
//интервал
Ti m егг. Interval:=500;
//текущая директория приложения
path:=GetCurrentDir;
// цвет фона
background:=RG 6(100,150,200);
рг:=77-5;
//ширина компонента
Main Form .Width :=round((Monitor.Width/ioo)*pr);
pr:=70;
//высота компонента
Main Form. Height:=round((Monitor. Height/ioo)*pr);
//позиция формы на дисплее
Main Form. Position :=poScreenCenter;
// заголовок формы
Main Form.Caption :='Тир';
//стиль границ формы
Main Form. BorderStyle:=bsSingle;
//разрешенные иконки формы
Main Form. Borderlcons:=[biSystem Menu];
// цвет формы
268
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Main Form. Color:=background;
//создание компонента
Paneli:=TPanel.Create(Self);
//родитель компонента
Paneli. Parent:=Main Form;
рг:=1;
//ордината левого верхнего угла компонента
Paneli.Top:=round((Monitor.Height/ioo)*pr);
рг-0.5;
//абсцисса левого верхнего угла компонента
Paneli. Left:=round((Monitor.Width/ioo)*pr);
pr:=22;
//ширина компонента
Paneli.Width:=round((Monitor.Width/ioo)*pr);
рг-64.5;
//высота компонента
Paneli. Height:=round((Monitor. Height/ioo)*pr);
//стиль внутренней границы компонента
Paneli. Bevel lnner:=bvRaised;
//стиль внешней границы компонента
Paneli. BevelOuter:=bvl_owered;
//цвет компонента
Paneli. Color:=background;
//создание компонента
Panel2:=TPanel.Create(Self);
//родитель компонента
Panel2.Parent:=MainForm;
рг:=1;
//ордината левого верхнего угла компонента
Panel2.Top:=round((Monitor.Height/ioo)*pr);
рг-23;
//абсцисса левого верхнего угла компонента
Panel2.l_eft:=round((Monitor.Width/ioo)*pr);
РГ:=53-5;
//ширина компонента
Panel2.Width:=round((Monitor.Width/ioo)*pr);
рг—64.5;
//высота компонента
Panel2.Height:=round((Monitor.Height/ioo)*pr);
//стиль внутренней границы компонента
Panel2. Bevel lnner:=bvRaised;
//стиль внешней границы компонента
269
РАЗРАБОТКА SCADA-СИСТЕМ
Panel2.BevelOuter:=bvLowered;
//цвет компонента
Panel2.Color:=background;
//создание компонента
Labeli:=TLabel.Create(Self);
//родитель компонента
Labeli.Parent:=Paneli;
//заголовок компонента
Labeli.Caption :='Музыка';
рг:=1;
//абсцисса левого верхнего угла компонента
Labeli. Left:=round((Monitor.Width/ioo)*pr);
рг:=1;
//ордината левого верхнего угла компонента
Labeli.Top:=round((Monitor.Height/ioo)*pr);
//размер шрифта компонента
Labeli. Font.Size:=i4;
//цвет шрифта компонента
Labeli. Font. Colored White;
//создание компонента
SelMusic:=TListBox.Create(Self);
//родитель компонента
Sei Music. Parent:=Paneli;
pr:=l;
//абсцисса левого верхнего угла компонента
Sei Music. Left:=round((Monitor.Width/ioo)*pr);
pr:=5;
//ордината левого верхнего угла компонента
SelMusic.Top:=round((Monitor.Height/ioo)*pr);
рг:=2О;
//ширина компонента
Sei Music.Width :=round((Monitor.Width/ioo)*pr);
рг-22.5;
//высота компонента
SelMusic.Height:=round((Monitor.Height/ioo)*pr);
//цвет компонента
SelMusic.Color:=background;
//цвет шрифта компонента
Sei Music. Font.Colored White;
//событие OnDblClick
SelMusic.OnDblClick:=SelMusicDblClicl<;
//создание компонента
270
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
l_abel2:=TI_abel.Create(Self);
//родитель компонента
l_abel2.Parent:=Paneli;
//заголовок компонента
Label 2.Caption :='3вук выстрела';
рг:=1;
//абсцисса левого верхнего угла компонента
Label2.Left:=round((Monitor.Width/ioo)*pr);
рг:=28;
//ордината левого верхнего угла компонента
Label2.Top:=round((Monitor.Height/ioo)*pr);
//размер шрифта компонента
Label2.Font.Size:=i4;
//цвет шрифта компонента
Label 2. Font.Colored White;
//создание компонента
SelSound :=TComboBox.Create(Self);
//родитель компонента
SelSound. Parent:=Paneli;
рг:=1;
//абсцисса левого верхнего угла компонента
SelSound. Left:=round((Monitor.Width/ioo)*pr);
рг-32;
//ордината левого верхнего угла компонента
SelSound.Top:=round((Monitor.Height/ioo)*pr);
рг:=2О;
//ширина компонента
SelSound. Width :=round((Monitor.Width/ioo)*pr);
рг:=з;
//высота компонента
SelSound. Height:=round((Monitor. Height/ioo)*pr);
//цвет компонента
SelSound. Color:=background;
//цвет шрифта компонента
SelSound. Font.Colored White;
//функция автопоиска строк в массиве Items по набранным
//буквам
SelSound. AutoComplete:=true;
//событие OnClick
SelSound.OnClick:=SelSoundCI ick;
//создание компонента
NoMusic:=TChecl<Box.Create(Self);
271
РАЗРАБОТКА SCADA-СИСТЕМ
//родитель компонента
NoMusic.Parent:=Paneli;
//заголовок компонента
NoM usic.Caption ^'Музыка';
//цвет шрифта компонента
NoM usic. Font.Colored White;
//размер шрифта компонента
NoM usic. Font. Size:=8;
pr-36;
//ордината левого верхнего угла компонента
NoMusic.Top:=round((Monitor.Height/ioo)*pr);
рг:=1;
//абсцисса левого верхнего угла компонента
NoM usic. Left:=round((Monitor.Width/ioo)*pr);
pr:=6;
//ширина компонента
NoM usic. Width :=round((Monitor.Width/ioo)*pr);
// флажок установлен
NoM usic.Checked:=true;
//событие OnClick
NoM usic.OnCliclc=NoM usicClick;
//создание компонента
Mode:=TRadioGroup.Create(Self);
//родитель компонента
Mode.Parent:=Paneli;
pr:=i;
//абсцисса левого верхнего угла компонента
Mode.Left:=round((Monitor.Width/ioo)*pr);
рг-39;
//ордината левого верхнего угла компонента
Mode.Top:=round((Monitor.Height/ioo)*pr);
рг:=2О;
//ширина компонента
Mode.Width :=round((Monitor.Width/ioo)*pr);
рг:=ю;
//высота компонента
Mode.Height:=round((Monitor.Height/ioo)*pr);
//цвет шрифта компонента
Mode. Font.Colored White;
//добавление строки
Mode. Items. Add ('Ре ж им i');
//добавление строки
272
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Mode.Items.АсИСРежим 2');
И заголовок компонента
Mode. Caption :='Режим';
//номер выбранного элемента
Mode. Item lndex:=o;
//событие OnClick
Mode.OnClick:=ModeClicl<;
//создание компонента
Shoots:=TI_abeledEdit.Create(Self);
//родитель компонента
Shoots. Parent:=Paneli;
pr:=l;
//абсцисса левого верхнего угла компонента
Shoots. Left:=round((Monitor.Width/ioo)*pr);
pr-52;
//ордината левого верхнего угла компонента
Shoots.Top:=round((Monitor.Height/ioo)*pr);
рг:=11.5;
//ширина компонента
Shoots.Width :=round((Monitor.Width/ioo)*pr);
рг:=5;
//высота компонента
Shoots. Height:=round((Monitor.Height/ioo)*pr);
//заголовок компонента
Shoots. EditLabel.Caption ^'Количество выстрелов';
//цвет шрифта заголовка
Shoots. EditLabel. Font. Colored White;
//размер шрифта заголовка
Shoots. EditLabel. Font.Size:=8;
//цвет компонента
Shoots. Color:=background;
//цвет шрифта компонента
Shoots. Font.Colored White;
//текст компонента
Shoots.Text :='ю';
Shoots. Enabled:=false;
//событие OnKeyPress
Shoots.On KeyPress:=ShootsKeyPress;
//событие OnChange
Shoots. OnChange:=ShootsChange;
//создание компонента
lnt:=TLabeledEdit.Create(Self);
273
РАЗРАБОТКА SCADA-СИСТЕМ
//родитель компонента
lnt.Parent:=Paneli;
рг:=1;
//абсцисса левого верхнего угла компонента
lnt.Left:=round((Monitor.Width/ioo)*pr);
рг-58;
//ордината левого верхнего угла компонента
lnt.Top:=round((Monitor.Height/ioo)*pr);
рг:=11.5;
//ширина компонента
lnt.Width:=round((Monitor.Width/ioo)*pr);
рг:=5;
//высота компонента
lnt.Height:=round((Monitor.Height/ioo)*pr);
//заголовок компонента
Int. EditLabel. Caption ^'Интервал (мс)';
//цвет шрифта заголовка
Int. EditLabel. Font.Colored White;
//размер шрифта заголовка
Int. EditLabel. Font.Size:=8;
//цвет компонента
lnt.Color:=background;
//цвет шрифта компонента
Int. Font.Colored White;
//текст компонента
lnt.Text:='iooo';
//компонент запрещен
lnt.Enabled:=false;
//событие OnKeyPress
lnt.Onl<eyPress:=lntl<eyPress;
//событие OnChange
lnt.OnChange:=lntChange;
//создание компонента
Start:=TButton.Create(Self);
//родитель компонента
Start. Parent:=Paneli;
pr-13.5;
//абсцисса левого верхнего угла компонента
Start. Left:=round((Monitor.Width/ioo)*pr);
pr-52;
//ордината левого верхнего угла компонента
Start.Top:=round((Monitor.Height/ioo)*pr);
274
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
IIзаголовок компонента
Start.Caption :='Старт';
IIсобытие OnClick
Sta rt.On Cl ick:=Sta rtCI ick;
II создание компонента
Stop:=TButton.Create(Self);
IIродитель компонента
Stop.Parent:=Paneli;
pr-13.5;
II абсцисса левого верхнего угла компонента
Stop.Left:=round((Monitor.Width/ioo)*pr);
рг-58;
II ордината левого верхнего угла компонента
Stop.Top:=round((Monitor.Height/ioo)*pr);
И заголовок компонента
Stop.Caption^'CTon';
II компонент запрещен
Stop. Enabled: =fa Ise;
IIсобытие OnClick
Stop.OnClick:=StopClicl<;
II создание компонента
Label3:=TI_abel.Create(Self);
IIродитель компонента
Label3.Parent:=Panel2;
И заголовок компонента
1_аЬе1з.Сар^оп:=/Выстрел: о';
рг:=1;
II абсцисса левого верхнего угла компонента
Label3.Left:=round((Monitor.Width/ioo)*pr);
рг:=1;
II ордината левого верхнего угла компонента
Label3.Top:=round((Monitor.Height/ioo)*pr);
IIразмер шрифта компонента
Label3.Font.Size:=i4;
II цвет шрифта компонента
1_аЬе1з. Font. Colored White;
II создание компонента
Target:=Tlmage.Create(Self);
IIродитель компонента
Target. Parent:=Panel2;
рг:=1;
II абсцисса левого верхнего угла компонента
275
РАЗРАБОТКА SCADA-СИСТЕМ
Target.Left:=round((Monitor.Width/ioo)*pr);
pr:=5;
//ордината левого верхнего угла компонента
Target.Top:=round((Monitor.Height/ioo)*pr);
рг-24;
//ширина компонента
Target.Width:=round((Monitor.Width/ioo)*pr);
//высота компонента
Target. Height:=Target.Width;
//создание компонента
Result:=TMemo.Create(Self);
//родитель компонента
Result. Parent:=Panel 2;
pr:=l;
//абсцисса левого верхнего угла компонента
Result. Left:=round((Monitor.Width/ioo)*pr);
pr:=39;
//ордината левого верхнего угла компонента
Result.Top:=round((Monitor.Height/ioo)*pr);
рг:=43;
//ширина компонента
Result.Width :=round((Monitor.Width/ioo)*pr);
рг-24;
//высота компонента
Result. Height:=round((Monitor. Height/ioo)*pr);
//цвет компонента
Result. Color:=background;
//размер шрифта компонента
Result. Font. Size:=i2;
//цвет шрифта компонента
Result. Font.Colored White;
//свойство «только чтение» компонента
Result. ReadOnly:=true;
//создание компонента
Clear:=TButton.Create(Self);
//родитель компонента
Clear. Parent:=Panel2;
pr:=45;
//абсцисса левого верхнего угла компонента
Clear. Left:=round((Monitor.Width/ioo)*pr);
pr-39;
//ордината левого верхнего угла компонента
276
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Clear.Top:=round((Monitor.Height/ioo)*pr);
И заголовок компонента
Clear.Caption ^'Очистка';
//событие OnClickкомпонента
Clear.OnCI ick:=ClearCI ick;
//создание компонента
Prnt:=TButton.Create(Self);
//родитель компонента
Prnt.Parent:=Panel2;
рг:=45;
//абсцисса левого верхнего угла компонента
Prnt.Left:=round((Monitor.Width/ioo)*pr);
рг:=44;
//ордината левого верхнего угла компонента
Prnt.Top:=round((Monitor.Height/ioo)*pr);
//заголовок компонента
Prnt.Caption ^'Печать';
//создание компонента
Ext:=TButton.Create(Self);
//родитель компонента
Ext.Parent:=Panel2;
рг:=45;
//абсцисса левого верхнего угла компонента
Ext.Left:=round((Monitor.Width/ioo)*pr);
рг:=49;
//ордината левого верхнего угла компонента
Ext.Top:=round((Monitor.Height/ioo)*pr);
//заголовок компонента
Ext. Caption :='Выход';
//событие OnClick
Ext.OnCI ick:=ExtCI ick;
//создание компонента
UpDown:=TUpDown.Create(UpDown);
//родитель компонента
UpDown.Parent:=Panel2;
рг:=2б;
//абсцисса левого верхнего угла компонента
UpDown.Left:=round((Monitor.Width/ioo)*pr);
рг:=5;
//ордината левого верхнего угла компонента
UpDown.Top:=round((Monitor.Height/ioo)*pr);
рг-32;
277
РАЗРАБОТКА SCADA-СИСТЕМ
//высота компонента
UpDown.Height:=round((Monitor.Height/ioo)*pr);
//событие OnClick
UpDown.OnClick:=UpDownClicl<;
//создание компонента
La bel 4:=TLa bel. Greate(Self);
//родитель компонента
Label4.Parent:=Panel2;
//заголовок компонента
Label/pCaption^'o из о';
рг-28.5;
//абсцисса левого верхнего угла компонента
Label4.Left:=round((Monitor.Width/ioo)'A'pr);
рг:=1;
//ордината левого верхнего угла компонента
Label4.Top:=round((Monitor.Height/ioo)*pr);
//размер шрифта компонента
Label4.Font.Size:=i4;
//цвет шрифта компонента
I_abel4. Font. Colored White;
//создание компонента
Total :=Tlmage.Create(Self);
//родитель компонента
Total. Parent:=Panel2;
pr-28.5;
//абсцисса левого верхнего угла компонента
Total. Left:=round((Monitor.Width/ioo)*pr);
pr:=5;
//ордината левого верхнего угла компонента
Total. Top:=round((Monitor. Height/ioo)*pr);
pr-24;
//ширина компонента
Total.Width :=round((Monitor.Width/ioo)*pr);
//высота компонента
Total. Height:=Total.Width;
//длина динамического массива music
lmusic:=o;
// если найден хотя бы один файл *.трз
if FindFirst(path+/\Music\/+/'A'.mp3//faAnyFile/SearchRec)=o then
begin
//длина динамического массива music
inc(lmusic);
278
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//установка динамического массива music
SetLength(m usic, I music);
//найденный файл
music[lmusic-i] :=Search Rec. Name;
//если найден следующий файл *.трз
while FindNext(SearchRec)=o do
begin
//длина динамического массива music
inc(lmusic);
//установка динамического массива music
SetLength(musiczlmusic);
//найденный файл
music[lmusic-i]:=SearchRec.Name;
end;
end;
//заполнение динамического массива Items компонента
//Se IM usic
for i:=o to Imusic-i do
//добавление элемента
SelMusic. Items. Add(music[i]);
//длина динамического массива sound
lsound:=o;
//если найден хотя бы один файл *.wav
if FindFirst(path+/\Sound\/+/'A'.wav//faAnyFilezSearchRec)=o then
begin
inc(lsound);
//установка длины динамического массива sound
SetLength(soundzlsound);
//найденный файл
sound[lsound-i]:=Search Rec. Name;
//если найден следующий файл *.wav
while FindNext(SearchRec)=o do
begin
//длина динамического массива sound
inc(lsound);
//установка длины динамического массива sound
SetLength(soundzlsound);
//найденный файл
sound[lsound-i]:=SearchRec.Name;
end;
end;
//заполнение динамического массива Items компонента
279
РАЗРАБОТКА SCADA-СИСТЕМ
//SelSound
for i:=o to Isound-i do
SelSound. Items. Add(sound[i]);
//номер выбранного элемента
SelSound. Item lndex:=o;
// имя проигрываемого файла
Speech. FileName:=path+'\Speech\'+'Danger.wav';
//открытие файла
Speech.Open;
end;
//происходит при закрытии формы
procedure TMainForm.FormClose(Sender: TObject; var Action:
TCIoseAction);
begin
// вызов дополнительной формы
AddForm.Show;
//закрытие проигрываемого файла
Msc.Close;
//закрытие проигрываемого файла
Weapon.Close;
//закрытие проигрываемого файла
Speech.Close;
//запрещение работы таймера
Timeri. Enabled :=false;
//запрещение работы таймера
Timer2. Enabled :=false;
//запрещение работы таймера
Add Form .Timen. Enabled :=false;
// вызов процедуры StopClick
StopClick(Stop);
end;
//происходит при двойном щелчке по компоненту SelMusic
procedure TMainForm.SelMusicDblClick(Sender: TObject);
begin
//выбор проигрываемого файла
Msc. FileName:=path+'\Music\'+music[Sel Music. Item Index];
//открытие файла
Msc.Open;
//воспроизведение файла
Msc.Play;
280
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//разрешение работы таймера
Timen. Enabled :=true;
end;
//происходит при щелчке мышью на компоненте SelSound
procedure TMainForm. SelSoundClick(Sender: TObject);
begin
//выбор проигрываемого файла
Weapon. FileName:=path+'\Sound\'+sound[SelSound. Item Index];
//открытие файла
Weapon.Open;
//воспроизведение файла
Weapon.Play;
end;
//происходит при щелчке мышью на компоненте NoMusic
procedure TMainForm. NoMusicClick(Sender: TObject);
begin
// если флажок снят
if not NoMusic.Checked then
begin
//закрытие файла
Msc.Close;
//запрещение работы таймера
Timeri. Enabled:=false;
//запрещение работы компонента
Sei Music. Enabled :=false;
end
// если флажок установлен
else
begin
//разрешение работы компонента
Sei Music. Enabled:=true;
//выбор проигрываемого файла
RandomMusic;
end;
end;
//выбор проигрываемого файла из списка
procedure RandomMusic;
begin
with MainForm do
281
РАЗРАБОТКА SCADA-СИСТЕМ
begin
//установка выбранного элемента
Sei Music. Item lndex:=random(lmusic);
//выбор проигрываемого файла
Msc.FileName:=path+'\Music\'+music[Sel Music. Item Index];
//открытие файла
Msc.Open;
//воспроизведение файла
Msc.Play;
//разрешение работы таймера
Timeri. Enabled :=true;
end;
end;
//происходит через заданный интервал
procedure TMainForm.TimenTimer(Sender: TObject);
begin
// если позиция указателя находится в конце файла
if Msc.Position=Msc.Length then
//выбор проигрываемого файла
RandomMusic;
end;
//отрисовывает мишень на Canvas
procedure lnitTarget(Canvas:TCanvas;w,h:integer);
var
//1/8 от w(h)
kreal;
// координаты углов прямоугольников
xi,yi,x2,y2\ integer;
//основной цвет мишени
coloninteger;
begin
//выбор цвета
color:=RGB(2Zh5/i28/3o);
//одна восьмая часть от ширины Canvas
k=w/8;
//координаты первого оранжевого прямоугольника
//абсцисса левого верхнего угла прямоугольника
Х1:=о;
//ордината левого верхнего угла прямоугольника
yi:=o;
282
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//абсцисса правого нижнего угла прямоугольника
X2:=w;
//ордината левого верхнего угла прямоугольника
y2:=h;
//цвет заливки прямоугольника
Canvas. Brush.Color:=color;
//отрисовка прямоугольника
Са n vas. Fi 11 Rect(Rect(xi/yi/x2/y 2));
//координаты первого зеленого прямоугольника
//абсцисса левого верхнего угла прямоугольника
xi:=round(l*i.5);
//ордината левого верхнего угла прямоугольника
yi:=round(l*i.5);
//абсцисса правого нижнего угла прямоугольника
X2:=xi+round(5*l);
//ордината правого нижнего угла прямоугольника
y2:=yi+round(5*l);
//цвет заливки прямоугольника
Canvas. Brush. Color:=clGreen;
//отрисовка прямоугольника
Саnvas. Fi11 Rect(Rect(xi/yi/x2/y2));
//координаты второго оранжевого прямоугольника
//абсцисса левого верхнего угла прямоугольника
xi:=round(l*2.5);
//ордината левого верхнего угла прямоугольника
yi:=round(l*2.5);
//абсцисса правого нижнего угла прямоугольника
X2:=xi+round(3*l);
//ордината правого нижнего угла прямоугольника
y2:=yi+round(3*l);
//цвет заливки прямоугольника
Canvas. Brush.Color:=color;
//отрисовка прямоугольника
Саnvas. Fi11 Rect(Rect(xi/yi/x2/y2));
//координаты второго зеленого прямоугольника
//абсцисса левого верхнего угла прямоугольника
xi:=round(l*3-5);
//ордината левого верхнего угла прямоугольника
yi:=round(l*3-5);
//абсцисса правого нижнего угла прямоугольника
X2:=xi+round(i*l);
//ордината правого нижнего угла прямоугольника
283
РАЗРАБОТКА SCADA-СИСТЕМ
y2:=yi+round(i*l);
//цвет заливки прямоугольника
Canvas. Brush. Color:=clGreen;
//отрисовка прямоугольника
Саnvas. Fi11 Rect(Rect(xi/yi/x2/y2));
end;
//отрисовка точки попадания на Canvas (ширина w и высота //h)
с номером s.
//Digit — признак, отвечающий за отрисовку цифры
//(количество попаданий в эту точку) внутри этой точки
//true рисовать; false не рисовать
procedure Bullet(Canvas:TCanvas;w/h:integer;s:integer;Digit:boolean);
var
// координаты углов прямоугольника
xi/yi/X2/y2: integer;
//одна восьмая от ширины (высоты) холста
kreal;
begin
// если номер точки не равен -1
if so-i then
begin
//одна восьмая от ширины (высоты) холста
I :=w/8;
//абсцисса левого верхнего угла прямоугольника
xi:=round((w/ioo)*Krd[s].x)-round(l/4);
//ордината левого верхнего угла прямоугольника
yi:=round((h/ioo)*Krd[s].y)-round(l/4);
//абсцисса правого нижнего угла прямоугольника
X2:=round((w/ioo)*l<rd[s].x)+round(l/4);
//ордината правого нижнего угла прямоугольника
y2:=round((h/ioo)*Krd[s].y)+round(l/4);
//цвет заливки
Canvas.Brush.Colored Black;
//отрисовка точки попадания
Canvas. El Iipse(xi/yi/x2/y2);
//размер шрифта
Canvas. Font.Size:=8;
// если Digit=true
if Digit then
begin
//цвет шрифта
284
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Canvas. Font. Color:=clGreen;
И вывод количества попаданий в точку
case krd[s].n of
0..9:
Canvas.TextOut(xi+round((x2-xi)/3)/yi+2/lntToStr(Krcl[s].n));
10. .99:
Canvas.TextOut(xi+round((x2-xi)/io)/yi+2/lntToStr(Krd[s].n));
else
Canvas.TextOut(xi-2/yi+2/lntToStr(Krd[s].n));
end;
end;
end;
end;
//щелчок на кнопке Clear (очистить)
procedure TMainForm.ClearClick(Sender: TObject);
var
//счетчик
i:integer;
begin
// заголовок
1_аЬе1з.Сар1юп:=/Выстрел: o';
// заголовок
Label^.Caption:='o из o';
//отрисовка мишени
lnitTarget(Target.CanvasJarget.Widtl^Target. Height);
//отрисовка мишени
lnitTarget(Total. CanvasJotal.WidthJotaL Height);
//количество выстрелов
n_shoot:=o;
//количество очков
pnts:=o;
//установка динамического массива
SetLength(shootzn_shoot);
//минимальное значение
UpDown.Min:=o;
//максимальное значение
U р Down. Мах:=о;
//текущая позиция
UpDown. Position :=о;
//приращение
UpDown. Increment:^;
285
РАЗРАБОТКА SCADA-СИСТЕМ
//очистка динамического массива Lines компонента Result(TMemo)
Result.Clear;
//обнуление количества попаданий в точку
for i:=o to n-i do
krd[i].n :=0;
end;
//щелчок на кнопке Ext
procedure TMainForm.ExtClick(Sender: TObject);
begin
//закрытие формы
Main Form.Close;
end;
//щелчок на компоненте UpDown
procedureTMainForm.UpDownClick(Sender:TObject; Button:
TUDBtnType);
begin
//отрисовка мишени
lnitTarget(Target.CanvasJarget.Widtl^Target. Height);
//отрисовка точки попадания
BulletCTarget.CanvasJarget.Width/rarget.Height.shoot
[UpDown. Rosition]zfalse);
// заголовок
1_аЬе1з.Сар^оп:=/Выстрел: 4lntToStr(UpDown.Position+i);
end;
//щелчок на компоненте Mode
procedure TMainForm.ModeClick(Sender: TObject);
begin
//выбор режима стрельбы
case Mode.Itemindex of
о: // режим i
begin
//запрет ввода количества выстрелов
Shoots. Enabled :=false;
//запрет ввода интервала между выстрелами
I nt. Enabled :=false;
//разрешение кнопки Start
Start. Enabled :=true;
end;
1; //режим 2
begin
286
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//разрешение ввода количества выстрелов
Shoots. Enabled :=true;
//разрешение ввода интервала стрельбы
I nt. Enabled :=true;
//если окна ввода текста не пусты
if (Shoots.Texto") and (Int.Texto") then
//разрешение кнопки Start
Start. Enabled:=true
else
//запрещение кнопки Start
Start. Enabled:=false;
end;
end;
end;
//происходит при вводе текста в окно редактирования Shoots
procedure TMainForm. ShootsKeyPress(Sender: TObject; var Key: Char);
begin
case Key of
//разрешенные символы
'o'..'9'/#8:
//остальные запрещены
else
Key:=#o;
end;
end;
//происходит при вводе текста в окно редактирования Int
procedure TMainForm. lntKeyPress(Sender: TObject; var Key: Char);
begin
case Key of
//разрешенные символы
чо'..'9'/#8:
//остальные запрещены
else
Key:=#o;
end;
end;
происходит при изменении текста в окнередактирования Shoots
procedure TMainForm. ShootsChange(Sender: TObject);
begin
287
РАЗРАБОТКА SCADA-СИСТЕМ
//если текста в окне нет
if Shoots.Text=" then
//запрещение кнопки
Start. Enabled :=false
else
//разрешение кнопки
Start. Enabled:=true;
end;
//происходит при изменении текста в окне редактирования Int
procedure TMainForm.lntChange(Sender: TObject);
begin
// если текста в окне нет
if lnt.Text=" then
//запрещение кнопки
Start. Enabled :=false
else
//разрешение кнопки
Start. Enabled:=true;
end;
//щелчок на кнопке Start
procedure TMainForm.StartClick(Sender: TObject);
begin
//запрещение кнопки Start
Start. Enabled:=false;
//разрешение кнопки Stop
Stop.Enabled:=true;
//запрещение компонента Mode
Mode.Enabled:=false;
//запрещение компонента Shoots
Shoots. Enabled :=false;
//запрещение компонента Int
lnt.Enabled:=false;
//запрещение компонента Clear
Clear. Enabled :=false;
//запрещение кнопки Prnt
Prnt.Enabled:=false;
// если выбран режим 2
if Mode.ltemlndex=i then
begin
// вызов процедуры ClearClick
ClearClick(Clear);
288
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//воспроизведение файла
Speech.Play;
//интервал таймера
Timer2. Interval:=StrTol nt(l nt.Text);
//разрешение работы таймера
Timer2. Enabled :=true;
//признак попадания в точку для режима 2
ff:=false;
end;
//разрешение работы таймера
AddForm .Timen. Enabled :=true;
end;
//щелчок на кнопке Stop
procedure TMainForm.StopClick(Sender: TObject);
begin
//разрешение кнопки Start
Start. Enabled:=true;
//запрещение кнопки Stop
Stop.Enabled:=false;
//разрешение компонента Mode
Mode. Enabled :=true;
// если выбран режим 2
if Mode.ltemlndex=i then
begin
//разрешение компонента Shoots
Shoots. Enabled:=true;
//разрешение компонента I nt
lnt.Enabled:=true;
//запрещение работы таймера
Timen. Enabled:=false;
end;
//разрешение кнопки Clear
Clear.Enabled:=true;
//разрешение кнопки Prnt
Prnt.Enabled:=true;
//запрещение работы таймера
Add Form .Timen. Enabled :=false;
end;
//проверка динамического массива krd — поиск точки попадания
procedure Check(varfound:boolean);
var
289
РАЗРАБОТКА SCADA-СИСТЕМ
//счетчик
i:integer;
begin
//признак попадания в точку для режима 1
fou nd: =fa Ise;
with MainForm do
//поиск точки попадания
for i:=o to n-i do
// если нашли точку
if krd[i].z=i then
begin
//признак попадания в точку для режима 1
found:=true;
//признак попадания в точку для режима 2
ff:=true;
//количество выстрелов
n_shoot:=n_shoot+i;
with krd[i] do
if (x<5o) and (y<5o) then
//добавление строки в динамический массив Lines
//компонента Result(TMemo)
Result.Lines.Add(lntToStr(n_shoot)+'. Слева, сверху
4lntToStr(points)+' очков!!!7)
else
if (x=5o) and (y<5o) then
//добавление строки в динамический массив Lines
//компонента Result(TMemo)
Result.Lines.Add(lntToStr(n_shoot)+'. Посередине, сверху
4+lntToStr(points)+7 очков!!!7)
else
if (x>5o) and (y<5o) then
//добавление строки в динамический массив Lines
//компонента Result(TMemo)
Result.Lines.Add(lntToStr(n_shoot)+7. Справа, сверху
4lntToStr(points)+7 очков!!!7)
else
if (x<5o) and (y=5o) then
//добавление строки в динамический массив Lines
//компонента Result(TMemo)
Result.Lines.Add(lntToStr(n_shoot)+7. Слева, посередине
4+lntToStr(points)+7 очков!!!7)
else
290
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
if (х=5<э) and (7=50) then
//добавление строки в динамический массив Lines
//компонента Result(TMemo)
Result.Lines.Add(lntToStr(n_shoot)+'. В центр
4+lntToStr(points)+7 очков!!!7)
else
if (x>5o) and (7=50) then
//добавление строки в динамический массив Lines
//компонента Result(TMemo)
Result.Lines.Add(lntToStr(n_shoot)+'. Справа, посередине
4lntToStr(points)+' очков!!!7)
else
if (x<5o) and (7>5o) then
//добавление строки в динамический массив Lines
//компонента Result(TMemo)
Result.Lines.Add(lntToStr(n_shoot)+7. Слева, СНИ37
4+lntToStr(points)+7 очков!!!7)
else
if (x=5o) and (7>5o) then
//добавление строки в динамический массив Lines
//компонента Result(TMemo)
Result.Lines.Add(lntToStr(n_shoot)+7. Посередине, СНИ37
4lntToStr(points)+7 очков!!!7)
else
//добавление строки в динамический массив Lines
//компонента Result(TMemo)
Result.Lines.Add(lntToStr(n_shoot)+7. Справа, СНИ37
4+lntToStr(points)+7 очков!!!7);
//максимальная величина
UpDown. Max:=n_shoot-i;
// если максимум =1
if UpDown.Max=i then
begin
//приращение
UpDown. Incremental;
//перерисовка компонента
UpDown.Repaint;
end;
//текущая позиция
UpDown. Position :=UpDown. Max;
//установка длины динамического массива
SetLength(shoot,n_shoot);
291
РАЗРАБОТКА SCADA-СИСТЕМ
//последний элемент динамического массива
shoot[n_shoot-i]:=i;
//количество очков
pnts:=pnts+krd [i] .points;
//количество попаданий в точку
krd[i].n:=krd[i].n+a;
// заголовок
Labelzh.Caption:=lntToStr(pnts)+/ из 4+lntToStr(n_shoot*io);
// заголовок
1_аЬе1з.Сар1юп:=/Выстрел: 4lntToStr(n_shoot);
//отрисовка мишени
lnitTarget(Target.Canvas,Target.Width,Target. Height);
//отрисовка точки попадания
Bullet(Target.Canvas,Target.Width,Target. Height, i,false);
//отрисовка точки попадания
Bullet(Total. Canvas,Total.Width,Total. Height, i,true);
// позиция указателя в проигрываемом файле
Weapon. Position :=о;
//воспроизведение файла
Weapon.Play;
//выход из процедуры
exit;
end;
end;
//происходит через определенный интервал времени
procedure TMainForm.Timer2Timer(Sender: TObject);
begin
//если не попали
if not ff then
begin
//количество выстрелов
n_shoot:=n_shoot+i;
//добавление строки в динамический массив Lines
//компонента Result(TMemo)
Result.Lines.Add(lntToStr(n_shoot)+'. Промах!!!');
//максимальная величина
U р Down. М ах:=n_sh oot-i;
// если максимум =1
if UpDown. Max=i then
begin
//приращение
292
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
UpDown. Incremental;
//перерисовка компонента
LlpDown.Repaint;
end;
//текущая позиция
UpDown. Position :=UpDown. Max;
//установка длины динамического массива
SetLength(shootzn_shoot);
//результат выстрела
shoot[n_shoot-i]:=-i;
// заголовок
1_аЬе1з. Caption ^'Выстрел: 4lntToStr(n_shoot);
//отрисовка мишени
lnitTarget(Target. CanvaszTarget.WidthzTarget. Height);
end;
//если количество выстрелов меньше, чем заданное число
if n_shoot<StrTolnt(Shoots.Text) then
begin
//воспроизведение файла
Speech.Play;
//признак попадания в точку для режима 2
ff:=false;
end
else
begin
//запрещение работы таймера
Timen. Enabled:=false;
//запрещение работы таймера
Add Form. Timen. Enabled :=false;
// вызов процедуры StopClick
StopClick(Stop);
end;
end;
end.
293
РАЗРАБОТКА SCADA-СИСТЕМ
На рис. 2.50 — 2.53 показано содержимое папок, хранящих
файлы данного проекта.
Music ^Tir.dof
Sound J^Tir.dpr
2J Speech ^Tir.exe
J] AddUnit.~ddp ^Tir.res
2j AddUnit.~dfm
21] AddUnit.~pas
2j AddUnit.dcu
2f AddUnit.ddp
j^AddUnit.dfm
AddUnit.pas
:T)AM.bmp
>1 AutoSave.sav
2jMain.~ddp
2j] Main.^dfm
Ц Main.-pas
2fMain.dcu
2[ Main, ddp
j^Main.dfm
Main .pas
2[OPCDA.dcu
S^OPCDA.pas
2f OPCtypes.dcu
sf OPCtypes.pas
Й OPOJtils.dcu
OPCutils.pas
^]Tir.~dpr
^Tir.cfg
Рис. 2.50. Содержимое папки проекта «Тир»
Рис. 2.51. Содержимое папки Music
294
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Рис. 2.52. Содержимое папки Sound
Рис. 2.53. Содержимое папки Speech
295
РАЗРАБОТКА SCADA-СИСТЕМ
2.8. SCADA-система для робота IRON BURATINO
На 9-й международной специализированной выставке «Пере-
довые Технологии Автоматизации. ПТА — 2009» кафедра «Авто-
матиз ации машино строения» Арз амас ского по л итехниче ско -
го института демонстрировала действующего учебного робота
IRON BURATINO (рис. 2.54). Робот может с помощью двух ша-
говых приводов перемещаться в горизонтальной плоскости. Кроме
этого, он имеет захватное устройство, которое может захватывать
небольшие детали. Поворотное устройство, в котором закреплено
захватное устройство, может поворачиваться вместе с деталью на
любой угол в диапазоне 0-150 градусов. Таким образом, робот мо-
жет выполнять следующие простейшие движения:
- захватывать деталь;
- перемещать деталь в горизонтальной плоскости по двум
осям на заданное расстояние;
- поворачивать деталь на нужный угол, который устанавли-
вается положением дискретного датчика;
- отпускать деталь.
Всего робот содержит 9 дискретных датчиков. Его положение в
горизонтальной плоскости системе управления известно, поскольку
использован шаговый привод.
Рис. 2.54. Учебный робот IRON BURATINO
296
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Система управления роботом реализована в виде КРСУ
(рис. 2.55).
Рис. 2.55. Система управления роботом
Нижний уровень КРСУ представлен контроллером ADAM-5510,
который содержит программу управления роботом в реальном вре-
мени. Все сложные движения представляют собой набор простей-
ших, выполняющихся последовательно друг за другом.
Программу управления роботом мы рассматривать в данной
работе не будем, однако отметим, что на выставке робот занимался
розливом жидкости. Информация с нескольких датчиков в реальном
времени передавалась по сети PLCNET на диспетчерский уровень.
На ноутбуке установлен ОРС-сервер Fastwel PLCNet ОРС Server
фирмы Fastwel и SCADA-система, реализованная в виде приложе-
ния, выполняющего графическую интерпретацию на экране мони-
тора всех перемещений робота и его манипуляций. На рис. 2.56 при-
ведена папка, хранящая проект SCADA-системы.
Bi Iron Buratino
Файл Правка Вид Избранное Сервис Справка
Поиск
Адрес: | 0:\Контроллер\1гоп Buratino
ла Переход
ЗЙ AddUnit. ~ddp
jgAddUnit.~dfm
AddUnit ,~pas
AddUnit. dcu
^AddUnit.ddp
^AddUnit. dfm
AddUnit. pas
E3J AM.bmp
aAM.jpg
,-j] AutoSave.sav
*3- Iron_Buratino.~dpr
R □ IronJBuratino.cfg
§ Iron_Buratino.dof
Iron_Buratino .dpr
Iron_Buratino.exe
,j±i| Iron_Buratino.res
»j)M3in.~ddp
Main.~dfm
2^ Main.-pas
jdj Main, de u
»f,Main.ddp
JJMain.dfm
Main.pas
^OPCDA.dcu
' jSj OPCtypes.dcu
OPCtypes.pas
§3] OPCUtils.dcu
sp OPCutils.pas
Объектов: 28
867 КБ
£ Мой компьютер
Рис. 2.56. Папка с проектом Iron Buratino
297
РАЗРАБОТКА SCADA-СИСТЕМ
Из рис. 2.56 видно, что приложение работает с двумя форма-
ми: AddForm и MainForm. Внешний вид этих форм приведен
на рис. 2.57 и 2.58 соответственно.
Рис. 2.58. Форма MainForm
Рис. 2.57. Форма AddForm
Компоненты, расположенные на форме AddForm, формируют-
ся динамически, т. е. программным образом во время работы прило-
жения. На форму MainForm выводится графическое изображение
робота во время его работы.
Программный код модуля AddUnit приведен в листинге 2.10.
Листинг 2.10
unit AddUnit;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics,
Controls, Forms, Dialogs, ExtCtrls, StdCtrls, Grids, CheckLst,
OPCDA, OPCTypes, OPCUtils, ComObj, ActiveX, DB, DBClient,
MConnect, SConnect, ComCtrls;
type
TAddForm = class(TForm)
Timeri: TTimer;
Timer2:TTimer;
//происходит при создании формы
procedure FormCreate(Sender: TObject);
//происходит при нажатии клавиши
// в поле редактирования Number
procedure NumberKeyPress(Sender: TObject; var Key:Char);
298
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//происходит при изменении текста
// в поле редактирования Number
procedure NumberChange(Sender:TObject);
//происходит по щелчку мыши
//по надписи ADD_Srvr
procedure ADD_SrvrClick(Sender:TObject);
//происходит по щелчку мыши
//по надписи ADD_OK
procedure ADD_OKCIick(Sender:TObject);
//происходит по щелчку мыши
//по надписи ADD_EXT
procedure ADD_EXTCIick(Sender:TObject);
//происходит при закрытии формы
procedure FormClose(Sender: TObject; var Action: TCIoseAction);
//происходит при уничтожении формы
procedure FormDestroy(Sender: TObject);
//происходит через заданный интервал времени
procedure TimenTimer(Sender: TObject);
//происходит при входе указателя в область надписи
procedure LabelMouseEnter(Sender: TObject);
//происходит при выходе указателя из области надписи
procedure LabelMouseLeave(Sender: TObject);
//происходит через заданный интервал времени
procedure Timer2Timer(Sender: TObject);
private
{Private declarations}
public
{Public declarations}
end;
//возвращает тип значения тега
function GetltemType(ltemValue:string):string;
var
//форма настройки
AddForm: TAdd Form;
//цвет фона
background:TColor;
//панели
ADD_PanelizADD_Panel2:TPanel;
//кнопки OK, «Сервер» и «Выход»
ADD_OK,ADD_Srvr,Add_EXT:TLabel;
//логотип
299
РАЗРАБОТКА SCADA-СИСТЕМ
Logo:Tlmage;
//компоненты для вывода названий сервера, сегмента и узла
Srv, Sgt, Node:TLabeled Edit;
//компонент для ввода числа каналов
Number:TLabeledEdit;
//таблица для ввода названий каналов
ltms:TStringGrid;
//имитатор загрузки программы
// для связи ОРС-клиента с ОРС-сервером
//необходимо время
Add_PB:TProgressBar;
//переменная, которая хранит результат операции
HR:HRESULT;
//интерфейс, с помощью которого осуществляется
//добавление и удаление тегов в группу
Segment: lOPCItemMgt;
//хэндл сегмента
SegmentHandle:OPCHANDLE;
//количество каналов
minteger;
//переменная для связи с ОРС-сервером на одном компьютере
Server: lOPCServer,
//массив переменных (тегов)
ltems:array of record
// Имя переменной (тега)
Ite mN a me: st ring;
//хэндл переменной (тега)
ltemHandle:OPCHANDLE;
//тип переменной (тега)
ltemType:TVarType;
//величина переменной (тега)
ltemValue:string;
//качество связи переменной (тега)
ltemQuality:word;
end;
//переменная, хранящая дату и время
dt:TDateTime;
//переменная для хранения текущей директории программы
р: st ring;
implementation
uses Main;
300
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
{$R *.dfm}
//возвращает тип значения тега
function GetltemType(ltemValue:string):string;
var
//счетчики
i,s:byte;
begin
//начальный результат
Result:='Timer';
//тип значения тега — Boolean
if (UpperCase(ltemValue)=/TRUE/) or
(UpperCase(ltemValue)=/FALSE/) then
begin
//значение функции
Result:='Boolean';
//выход из функции
exit;
end;
//цикл no значению тега
for i:=i to Length(ltemValue) do
//если в значении тега присутствует
//запятая или точка
if (ltemValue[i]=7) or (ItemVaIue[i]then
begin
//результат функции
Result:='Float';
//выход из процедуры
exit;
end;
//начальное значение счетчика
s:=o;
//цикл по значению тега
for i:=i to Length(ltemValue) do
// если 7 символ строки равен цифре или знаку плюс
// или минус
if ltemValue[i] in [чо717273//Ч75///67778797"7+/] then
//увеличение значения счетчика
inc(s);
//если длина строки равна значению счетчика
if s=Length(ltemValue) then
begin
//результат функции
301
РАЗРАБОТКА SCADA-СИСТЕМ
Resu It:='l nteger';
//выход из функции
exit;
end;
end;
// выполняеется при создании формы
procedure TAddForm.FormCreate(Sender: TObject);
var
//счетчик
i:integer;
//промежуточная переменная
pnreal;
//файловая переменная
f:TextFile;
//промежуточная переменная
s:string;
begin
//запись текущей директории программы
p:=GetCurrentDir;
//начальное значение
Segment:=nil;
//начальное значение
Server:=nil;
//запрещение таймера
Timen. Enabled :=false;
//интервал таймера
Timen. Interval:=юо;
//запрещение таймера
Timer2. Enabled :=false;
//интервал таймера
Ti me Г2. Interval:=юоо;
// число каналов по умолчанию
п:=8;
//длина динамического массива переменных
SetLength(ltems,n);
//начальное значение полей ItemValue
for i:=o to n-i do
ltems[i]. Item Vai ue:='o';
// цвет фона
background:=RG 8(100,150,200);
pr:=5o;
302
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//ширина компонента
Add Form .Width :=round((Monitor.Width/ioo)*pr);
pr-30;
//высота компонента
Add Form. Height:=round((Monitor. Height/ioo)*pr);
//позиция формы на дисплее
Add Form. Position :=poScreenCenter;
// заголовок формы
AddForm.Caption ^'Настройка ОРС-сервера';
//стиль границ формы
AddForm. BorderStyle:=bsSingle;
//разрешенные иконки на форме
Add Form. Borderlcons:=[biSystem Menu];
// цвет формы
Add Form.Color:=background;
//создание панели, на которой расположены компоненты
//названий ОРС-сервера, сегмента и узла
//создание компонента
ADD_Paneli:=TPanel.Create(Self);
//родитель компонента
ADD_Paneli.Parent:=AddForm;
рг:=1;
//ордината левого верхнего угла компонента
ADD_Paneli.Top:=round((Monitor.Height/ioo)*pr);
рг-0.5;
//абсцисса левого верхнего угла компонента
ADD_Paneli.Left:=round((Monitor.Width/ioo)*pr);
рг-48.5;
//ширина компонента
ADD_Paneli.Width:=round((Monitor.Width/ioo)*pr);
рг:=8;
//высота компонента
ADD_Paneli.Height:=round((Monitor.Height/ioo)*pr);
//стиль внутренней границы компонента
ADD_Paneli. Bevel lnner:=bvRaised;
//стиль внешней границы компонента
ADD_Paneli.BevelOuter:=bvl_owered;
//цвет компонента
ADD_Paneli.Color:=background;
//создание компонента для вывода названия сервера
//создание компонента
Srv: =TI_a beled Ed it. Create(Self);
303
РАЗРАБОТКА SCADA-СИСТЕМ
//родитель компонента
Srv.Parent:=ADD_Paneli;
рг:=з;
//ордината левого верхнего угла компонента
Srv.Top:=round((Monitor.Height/ioo)*pr);
рг-1.5;
//абсцисса левого верхнего угла компонента
Srv.Left:=round((Monitor.Width/ioo)*pr);
//авторазмер компонента
Srv.AutoSize:=false;
//размер шрифта компонента
Srv.Font.Size:=io;
//цвет компонента
Srv.Color:=clWhite;
рг:=з;
//высота компонента
Srv.Height:=round((Monitor.Height/ioo)*pr);
рг-17;
//ширина компонента
Srv.Width:=round((Monitor.Width/ioo)*pr);
//заголовок компонента
Srv. EditLabel. Caption^'OPC-Server';
Srv. EditLabel. Font.Colored White;
//свойство text компонента
Srv.Text:='Fastwel.PLCNetOPC';
//создание компонента для вывода названия сегмента
//создание компонента
Sgt:=TLabeled Ed it.Create(Self);
//родитель компонента
Sgt.Parent:=ADD_Paneli;
рг:=з;
//ордината левого верхнего угла компонента
Sgt.Top:=round((Monitor.Height/ioo)*pr);
рг:=2О;
//абсцисса левого верхнего угла компонента
Sgt.Left:=round((Monitor.Width/ioo)*pr);
//авторазмер компонента
Sgt.AutoSize:=false;
//размер шрифта компонента
Sgt. Font. Size:=io;
//цвет компонента
Sgt. Color:=clWhite;
304
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
рг-з;
//высота компонента
Sgt.Height:=round((Monitor.Height/ioo)*pr);
рг-17;
//ширина компонента
Sgt.Width :=round((Monitor.Width/ioo)*pr);
//заголовок компонента
Sgt. EditLabel. Caption :='Сегмент UltraNet';
Sgt. EditLabel. Font.Colored White;
//свойство text компонента
Sgt.Text:='Ultranet_i';
//создание компонента для вывода названия узла
//создание компонента
Node:=TLabeled Ed it. Create(Self);
//родитель компонента
Node.Parent:=ADD_Paneli;
рг:=з;
//ордината левого верхнего угла компонента
Node.Top:=round((Monitor.Height/ioo)*pr);
рг-38.5;
//абсцисса левого верхнего угла компонента
Node.Left:=round((Monitor.Width/ioo)*pr);
//авторазмер компонента
Node.AutoSize:=false;
//размер шрифта компонента
Node. Font. Size:=10;
//цвет компонента
Node.Colored White;
рг:=з;
//высота компонента
Node.Height:=round((Monitor.Height/ioo)*pr);
pr-8.5;
//ширина компонента
Node. Width :=round((Monitor.Width/ioo)*pr);
//заголовок компонента
Node. EditLabel. Сарйоп:='Узел';
Node. EditLabel. Font.Colored White;
//свойство text компонента
Node.Text:='FE';
//создание компонента
ADD_Panel2:=TPanel.Create(Self);
//родитель компонента
305
РАЗРАБОТКА SCADA-СИСТЕМ
ADD_Panel2.Parent:=AddForm;
pr:=io;
//ордината левого верхнего угла компонента
ADD_Panel2.Top:=round((Monitor.Height/ioo)*pr);
рг-0.5;
//абсцисса левого верхнего угла компонента
ADD_Panel2.Left:=round((Monitor.Width/ioo)*pr);
рг-48.5;
//ширина компонента
ADD_Panel2.Width:=round((Monitor.Width/ioo)*pr);
рг:=16;
//высота компонента
ADD_Panel2.Height:=round((Monitor.Height/ioo)*pr);
//стиль внутренней границы компонента
ADD_Panel2. Bevel lnner:=bvRaised;
//стиль внешней границы компонента
ADD_Panel2.BevelOuter:=bvl_owered;
//цвет компонента
ADD_Panel2.Color:=background;
//создание компонента
Number:=TI_abeledEdit.Create(Self);
//родитель компонента
Number. Parent:=ADD_Panel 2;
pr-з;
//ордината левого верхнего угла компонента
Number.Top:=round((Monitor.Height/ioo)*pr);
рг-1.5;
//абсцисса левого верхнего угла компонента
Number. Left:=round((Monitor.Width/ioo)*pr);
//авторазмер компонента
Number. AutoSize:=false;
//размер шрифта компонента
Number. Font. Size:=io;
//цвет компонента
Number.Color:=cl White;
//цвет текста
Number. EditLabel. Font.Colored White;
рг:=з;
//высота компонента
Number. Height:=round((Monitor. Height/ioo)*pr);
pr:=ii;
//ширина компонента
306
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Number.Width:=round((Monitor.Width/ioo)*pr);
И заголовок компонента
Number.EditLabel.Caption^'Hi/icno тегов';
//свойство text компонента
Number.Text:='8';
//обработчик события OnKeyPress компонента
Number.OnKeyPress:=NumberKeyPress;
//обработчик события OnChange компонента
Number.OnChange:=NumberChange;
//создание компонента
ltms:=TStringGrid.Create(Self);
//родитель компонента
ltms.Parent:=ADD_Panel2;
рг-14;
//абсцисса левого верхнего угла компонента
ltms.Left:=round((Monitor.Width/ioo)*pr);
рг:=1;
//ордината левого верхнего угла компонента
ltms.Top:=round((Monitor.Height/ioo)*pr);
рг:=33;
//ширина компонента
Itms.Width :=round((Monitor.Width/ioo)*pr);
pr:=io;
//высота компонента
ltms.Height:=round((Monitor.Height/ioo)*pr);
//цвет компонента
ltms.Color:=clWhite;
//цвет фиксированных строк и столбцов компонента
Itms. Fixed Col or:=cl White;
//цвет текста
Itms. Font.Colored Black;
// число столбцов компонента
ltms.ColCount:=n+i;
// число строк компонента
ltms.RowCount:=2;
pr:=8;
//ширина столбцов компонента
Itms. DefaultCol Width :=round((Monitor. Width/ioo)*pr);
//заполнение ячеек таблицы названий каналов (переменных)
Itms.CellstO/Oj^'HoMep';
Itms.Cel 15[о/1]:='Имя';
for i:=i to n do
307
РАЗРАБОТКА SCADA-СИСТЕМ
begin
Itms. Cel ls[i, о]:='Тег 4lntToStr(i);
Itms. Cel ls[i/i]:=/Vxod/+lntToStr(i);
end;
//настройка опций компонента
Itms OptionsiHgoFixedVertLine^oFixedHorzLine^oVertLine,
goHorzLine, goRangeSelectzgoEditing];
//создание компонента
Logo:=Tlmage.Create(Self);
//родитель компонента
Logo.Parent:=ADD_Panel2;
pr-1.5;
//абсцисса левого верхнего угла компонента
Logo.Left:=round((Monitor.Width/ioo)*pr);
рг:=8;
//ордината левого верхнего угла компонента
Logo.Top:=round((Monitor.Height/ioo)*pr);
рг:=ю;
//ширина компонента
Logo.Width :=round((Monitor.Width/ioo)*pr);
рг-7;
//высота компонента
Logo.Height:=round((Monitor.Height/ioo)*pr);
//загрузка картинки
Logo. Picture. Load From FileCAM.bmp');
//создание компонента
ADD_Srvr:=Tlabel.Create(Self);
//родитель компонента
ADD_Srvr.Parent:=ADD_Panel2;
//заголовок компонента
ADD_Srvr.Caption:='CEPBEP';
//цвет текста
ADD_Srvr. Font. Colored White;
//размер шрифта
ADD_Srvr.Font.Size:=i4;
pr-27.5;
//абсцисса левого верхнего угла компонента
ADD_Srvr.Left:=round((Monitor.Width/ioo)*pr);
рг:=12;
//ордината левого верхнего угла компонента
ADD_Srvr.Top:=round((Monitor.Height/ioo)*pr);
рг:=8;
308
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//ширина компонента
ADD_Srvr.Width:=round((Monitor.Width/ioo)*pr);
РГ:=3-5;
//высота компонента
ADD_Srvr.Height:=round((Monitor.Height/ioo)*pr);
//обработчик события OnClickкомпонента
ADD_Srvr.OnClick:=ADD_SrvrClicl<;
//обработчик события OnMouseEnter
ADD_Srvr.OnMouseEnter:=l_abelMouseEnter;
//обработчик события OnMouseLeave
ADD_Srvr.OnMouseLeave:=LabelMouseLeave;
//создание компонента
ADD_OK:=TLabel.Create(Self);
//родитель компонента
ADD_OK.Parent:=ADD_Panel2;
//заголовок компонента
ADD_OK.Caption :='0К';
//цвет текста
ADD_OK. Font. Colored White;
//размер текста
ADD_OK.Font.Size:=i4;
рг:=з6;
//абсцисса левого верхнего угла компонента
ADD_OK.Left:=round((Monitor.Width/ioo)*pr);
рг:=12;
//ордината левого верхнего угла компонента
ADD_OK.Top:=round((Monitor.Height/ioo)*pr);
рг:=6;
//ширина компонента
ADD_OK.Width:=round((Monitor.Width/ioo)*pr);
РГ:=3-5/’
//высота компонента
ADD_OK.Height:=round((Monitor.Height/ioo)*pr);
//обработчик события OnClickкомпонента
ADD_0K.0nClick:=ADD_0KCIick;
//обработчик события OnMouseEnter
ADD_OK.OnMouseEnter:=LabelMouseEnter;
//обработчик события OnMouseLeave
ADD_OK.OnMouseLeave:=LabelMouseLeave;
//создание компонента
ADD_EXT:=TLabel.Create(Self);
//родитель компонента
309
РАЗРАБОТКА SCADA-СИСТЕМ
ADD_EXT.Parent:=ADD_Panel2;
И заголовок компонента
ADD_EXT.Caption:='BblXOfl';
//цвет текста
ADD_EXT.Font.Color:=clWhite;
//размер текста
ADD_EXT.Font.Size:=i4;
рг-40;
//абсцисса левого верхнего угла компонента
ADD_EXT.Left:=round((Monitor.Width/ioo)*pr);
рг:=12;
//ордината левого верхнего угла компонента
ADD_EXTJop:=round((Monitor.Height/ioo)*pr);
рг:=8;
//ширина компонента
ADD_EXT.Width:=round((Monitor.Width/ioo)'A'pr);
РГ:=3-5;
//высота компонента
ADD_EXT.Height:=round((Monitor.Height/ioo)*pr);
//обработчик события OnClickкомпонента
ADD_EXT.0nClick:=ADD_EXTCIick;
//обработчик события OnMouseEnter
ADD_EXT.OnMouseEnter:=LabelMouseEnter;
//обработчик события OnMouseLeave
ADD_EXT.OnMouseLeave:=LabelMousel_eave;
//создание компонента
Add_PB:=TProgressBar.Create(Self);
//родитель компонента
Add_PB.Parent:=ADD_Panel2;
рг-14;
//абсцисса левого верхнего угла компонента
Add_PB.Left:=round((Monitor.Width/ioo)*pr);
рг:=12.5;
//ордината верхнего левого угла компонента
Add_PBTop:=round((Monitor.Height/ioo)*pr);
рг:=12.5;
//ширина
Add_PB.Width :=round((Monitor.Width/ioo)'A'pr);
pr:=2;
//высота
Add_PB.Height:=round((Monitor.Height/ioo)*pr);
//минимальное возможное значение
310
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Add_PB.Min:=o;
//максимальное возможное значение
Add_PB.Max:=io;
//позиция
Add_PB. Position :=о;
//поиск файла и чтение текущих верхних
//и нижних границ измеряемой величины
//поиск файла AutoSave.savв текущем каталоге
// если файл существует
if FileExistsCAutoSave.sav') then
begin
// связь файловой переменной с файлом
AssignFile(f,'AutoSave.sav');
//открытие файла для чтения
Reset(f);
//чтение названия сервера
readings);
//свойство text компонента
Srv.Text:=s;
//чтение имени сегмента
readings);
//свойство text компонента
Sgt.Text:=s;
//чтение имени узла
readings);
//свойство text компонента
N ode.Text:=s;
//чтение числа тегов
readln(f/s);
//свойство text компонента
Number.Text:=s;
//если свойство text состоит из нуля символов
if Number.Text=" then
//число тегов
п:=о
else
//число тегов
n:=StrTolnt(Number.Text);
//длина динамического массива
SetLength(ltemszn);
//цикл по п каналам
for i:=o to n-i do
311
РАЗРАБОТКА SCADA-СИСТЕМ
//начальное значения величины тега
ItemsfiJ.ltemValue^'o';
//число столбцов в таблице имен тегов
ltms.ColCount:=n+i;
// если число тегов не равно нулю
if noo then
begin
// число фиксированных столбцов в таблице имен тегов
ltms.FixedCols:=i;
// цикл по п тегам
for i:=i to n do
begin
// имя ячейки
Itms.Cellsti/Oj^'Ter 4lntToStr(i);
// имя ячейки
ltms.Cells[i/i]:=/Vxod/+lntToStr(i);
end;
end;
//чтение имен тегов
for i:=o to n-i do
begin
//чтение имени тега
readings);
//свойство text компонента
Itms.Cellsfi+i/iJ^s;
end;
//закрытие файла
CloseFile(f);
end;
end;
//происходит при изменении текста в компоненте Number
procedure TAddForm.NumberChange(Sender: TObject);
var
//счетчик цикла
i:integer;
begin
//запрещение работы таймера
Timeri. Enabled :=false;
// если свойство text состоит из нуля символов
if Number.Text=" then
//число тегов
312
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
П:=о
else
//число тегов
n:=StrTolnt(Number.Text);
//длина динамического массива
SetLength(ltems/n);
//цикл по п тегам
for i:=o to n-i do
//начальное значение тега
ltems[i]. Item Vai ue:='o';
//числа столбцов в таблице имен тегов
ltms.ColCount:=n+i;
// если число тегов не равно нулю
if noo then
begin
// число фиксированных столбцов в таблице имен тегов
ltms.FixedCols:=i;
// цикл по п тегам
for i:=i to n do
begin
// имя ячейки
Itms.Cellsti/Oj^'Ter 4lntToStr(i);
// имя ячейки
ltms.Cells[i/i]:=/Vxod/+lntToStr(i);
end;
end;
end;
//происходит при нажатии клавиши на компоненте Number
procedure TAddForm. NumberKeyPress(Sender: TObject; var Key: Char);
begin
case key of
//разрешенные символы
'o'..'9'/#8:
else
//остальные запрещены
key:=#o;
end;
end;
//происходит при клике мышью по кнопке ADD_Srvr
procedure TAddForm.ADD_SrvrClick(Sender: TObject);
begin
313
РАЗРАБОТКА SCADA-СИСТЕМ
try
//создание ОРС-сервера
Server:=CreateComObject(ProglDToClasslD(Srv.Text)) as lOPCServer;
// если произошла ошибка
except
// показ сообщения об ошибке
ShowMessage('He могу запустить сервер!!!7);
//уничтожение сервера
Server:=nil;
end;
end;
//происходит при клике мышью по кнопке ADD_OK
procedure TAddForm.ADD_OKCIick(Sender: TObject);
var
//счетчик цикла
i:integer;
begin
// если число тегов равно нулю
if n=o then
begin
//сообщение
ShowMessage('Heo6xoAMMO добавить хотя бы один тег!!!7);
//выход из процедуры
exit;
end;
//запрещение работы таймера
Timeri. Enabled :=false;
//уничтожение сервера
Server:=nil;
try
//создание сервера
Server:=CreateComObject(ProglDToClasslD(Srv.Text)) as lOPCServer;
// если не смогли создать сервер
except
//показ сообщения об ошибке
ShowMessage('He могу запустить сервер!!!7);
//уничтожение сервера
Server:=nil;
//выход из процедуры
Exit;
end;
314
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
И если сегмент Ultranet не добавлен
if Segment=nil then
//добавление сегмента
HR:=ServerAddGroup(Server,Sgt.Text,true, 500,о, Segment,
SegmentHandle);
//если произошла ошибка
if Failed(HR) then
begin
//показ сообщения об ошибке
ShowMessage('He могу добавить сегмент UltraNet!!!7);
//уничтожение сервера
Server:=nil;
//выход из процедуры
Exit;
end;
//добавление тегов в сегмент
for i:=o to n-i do
begin
//полное имя тега
ltems[i]. Item Name:=Sgt.Text+7+Node.Text+7+ltms.Cel ls[i+i,i];
// если тега не существует
if ltems[i].ltemHandle=o then
//добавление тега
HR:=GroupAddltem(Segment,ltems[i]. Item Name,SegmentHandle,
VT_EM PTY, ltems[i]. Item Handle, ltems[i].ltemType);
// если произошла ошибка
if Failed(HR) then
begin
// показ сообщения об ошибке
ShowMessage('He могу добавить переменную
'+ltems[i].ltemName+' !!!');
//уничтожение сервера
Server:=nil;
//выход из процедуры
Exit;
end;
end;
//разрешение работы таймера
Timen. Enabled :=true;
Timer2. Enabled :=true;
end;
315
РАЗРАБОТКА SCADA-СИСТЕМ
//происходит по закрытию формы
procedureTAddForm.FormClose(Sender:TObject; var Action:
TCIoseAction);
var
//переменная для хранения выбранного действия
//пользователя
inf:Word;
//файловая переменная
f:TextFile;
//счетчик цикла
i:integer;
begin
//вызов диалогового окна для закрытия формы
inf:=MessageDlg('Bbi уверены?', mtlnformation, [mbYes/mbNo]/o);
// если нажата кнопка Yes
if inf=mrYes then
begin
// связь файловой переменной с файлом
Assign File(f, 'AutoSave.sav');
//перезапись файла
Rewrite(f);
//запись названия сервера
write I n(f,Srv.Text);
//запись названия сегмента
writeln(f,Sgt.Text);
//запись названия узла
writeln(f,Node.Text);
//запись числа тегов
write In (f, num be г. text);
//запись имен тегов
for i:=o to n-i do
//запись имени тега
writeln(f,ltms.Cells[i+i/i]);
//закрытие файла
CloseFile(f);
//запрещение работы таймера
Timeri. Enabled :=false;
//уничтожение сервера
Server:=nil;
//длина динамического массива в нуль элементов
SetLength(ltems,o);
//разрешение на закрытие главной формы
316
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Action:=caFree;
//закрытие приложения
Application.Terminate;
end
// если нажата кнопка No
else
//отмена закрытия главной формы
Action:=caNone;
end;
//происходит при уничтожении формы
procedure TAddForm. FormDestroy(Sender: TObject);
begin
//уничтожение сервера
Server:=nil;
//длина динамического массива
SetLength(ltems,o);
end;
//происходит через определенный интервал времени
procedure TAddForm.TimenTimer(Sender: TObject);
var
//счетчик цикла
i:integer;
begin
//чтение даты и времени
dt:=Now;
//чтение значений измеряемых величин из ОРС-сервера
for i:=o to n-i do
begin
//чтение в переменные ItemValue и ItemQuality
//из сегмента Segment значения и качества связи тега
//с хэндлом Item Handle
HR:=ReadOPCGroupltemValue(Segment, ItemsfiJ. Item Handle,
Itemsfi].ItemValue, Itemsfi].ItemQuality);
// если прочитали без ошибок
if Succeeded(HR) then
// если тип тега float
if GetltemType(ltems[i]. Item Value)='FLOAT'then
begin
//если измеряемая величина станет меньше ofooi
if StrToFloat(ltems[i].ltemValue)<o.ooi then
317
РАЗРАБОТКА SCADA-СИСТЕМ
//ItemValue в нуль
ltems[i].ltemValue:='o';
//округление измеряемой величины
ltems[i]. Item Value:=FloatToStrF(StrToFloat(ltems[i]. Item Value),
fffixed/5,3);
end;
end;
end;
//происходит при щелчке мыши по надписи ADD_EXT
procedure TAddForm.ADD_EXTCIick(Sender: TObject);
begin
//закрытие формы
AddForm.Close;
end;
//происходит через определенный интервал времени
procedure TAddForm.Timer2Timer(Sender: TObject);
begin
//текущая позиция
Add_PB. Position :=Add_PB. Position +i;
//если позиция достигает максимального значения
if Add_PB.Position=Add_PB.Max then
begin
//запрет работы таймера
Timer2.Enabled:=false;
// вызов главной формы
MainForm.Show;
//позиция
Add_PB. Position :=o;
end;
end;
//происходит при попадании указателя мыши в область надписи
procedure TAddForm.LabelMouseEnter(Sender: TObject);
var
//надпись
IbkTLabel;
begin
//ссылка на надпись, у которой произошло событие
I bl:^Sender as TLabel;
//цвет надписи
318
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Ibl. Font.Colored Purple;
end;
//происходит при покидании указателя мыши области надписи
procedure TAddForm.LabelMouseLeave(Sender: TObject);
var
//надпись
IbkTLabel;
begin
//ссылка на надпись, у которой произошло событие
lbl:=Sender asTLabel;
// цвет надписи
Ibl. Font. Colored White;
end;
end.
Программный код модуля Main приведен в листинге 2.11.
Листинг 2.11
unit Main;
interface
uses
Windows, Messages, Syslltils, Variants, Classes, Graphics,
Controls, Forms, Dialogs, ExtCtrls;
type
TMainForm = class(TForm)
Timeri: TTimer;
Timer2: TTimer;
Time^: TTimer;
//происходит при создании формы
procedure FormCreate(Sender: TObject);
//происходит при нажатии клавиши на форме
procedure FormKeyPress(Sender: TObject; var Key: Char);
//происходит через определенный интервал времени
procedure TimenTimer(Sender: TObject);
//происходит после появления формы
319
РАЗРАБОТКА SCADA-СИСТЕМ
procedure FormShow(Sender: TObject);
//происходит при закрытии формы
procedure FormClose(Sender:TObject;var Action: TCIoseAction);
//происходит через определенный интервал времени
procedure Timer2Timer(Sender: TObject);
//происходит через определенный интервал времени
procedure Timer3Timer(Sender: TObject);
private
{Private declarations}
public
{Public declarations}
end;
type
//запись, содержащая координаты и цвет прямоугольника
t_rct=record
// цвет
coloninteger;
//массив координат
rct:array[o..3] of record
//координаты
x^zireal;
end;
end;
//запись, содержащая массив прямоугольников,
// образующих какую-либо фигуру в пространстве
t_figure=record
//количество прямоугольников
I rets integer;
//массив прямоугольников
rets:array of t_rct;
//координаты центра фигуры
xo.yo.zoireal;
//координаты плавающего центра
//определяются по значениям
// тегов ОРС-сервера
xc.yc.zcreal;
//видимость фигуры
v:boolean;
//угол наклона фигуры
//используется при повороте
и integer;
end;
320
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//запись, содержащая массив экранных координат полигона,
// сумму z-координат точек и цвет фигуры
t_polygon=record
//массив экранных координат
plgn:array[o..4] ofTPoint;
// сумма z-координат точек
total_z:real;
//цвет фигуры
coloninteger;
end;
const
//максимальный угол наклона
тах_ии=юо;
//минимальный угол наклона
min_uu=o;
//время поворота в мс
time_rotation=i5oo;
//граница (градусы), которая определяет
//порядокрасположения некоторых фигур на экране
gran=30;
var
//главная форма
MainForm: TMain Form;
//изображение, на котором отрисовывается графика
lmg:Tlmage;
//количество элементов массива ms
Imsdnteger;
//массив фигур
т s: a rray of t_fi g и re;
//массив, элементы которого определяют
//порядок от рисовки фигур
mas:array of byte;
//количество элементов массива polygons
lpolygons:integer;
//массив всех полигонов
polygons:array of t_polygon;
//положение плоскости проецирования
alpha, beta:integer;
//коэффициенты масштабирования
dx,dy:integer;
//текущий каталог приложения
CurrDinstring;
321
РАЗРАБОТКА SCADA-СИСТЕМ
//прямоугольная область,
// в которой отрисовывается графика
R:TRect;
//переменные, в которые считываются
//значения тегов ОРС-сервера
ti,t2 integer;
t3/t4/t5:boolean;
//значение перемещения по нижнему основанию
ttureal;
//значение перемещения по верхнему основанию
tt2:real;
// текущий угол наклона фигур
uu:integer;
//перевод строки в boolean
function StrToBool(Value:string):boolean;
//осуществляет поворот точки вокруг оси оу
procedure GetXYZaroundY(var XXzYYzZZ:real;xzyzz:real;u:integer);
//перевод мировых координат в экранные
procedure GetXXYYZZ(varXXfYYfZZ:real; xzyzz:real;aazbb:integer);
//расчет координат для всех полигонов массива polygons
procedure Get_Polygons;
//заполняет поля записи t_rct
procedure Set_Rcts(var rct:t_rct;
Xi/yi/zi/x2/y2/z2/x3/y3/z3/x4/y4/z4:real;clr:integer);
implementation
uses AddUnit;
{$R *.dfm}
//перевод строки в Boolean
function StrToBool(Value:string):boolean;
begin
//если значение строки true
if UpperCase(value)=/TRUE/ then
//значение функции
Result:=true
else
//значение функции
Result:=false;
end;
322
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//перевод мировых координат в экранные
procedure GetXXYYZZ(var XX/YY/ZZ:real;x/y/z:real;aa/bb:integer);
const
//градус в радианах
gr=pi/i8o;
begin
//координатах
XX:=x*cos(aa*gr)-y*sin(aa*gr);
//координата у
YY:=x*sin(aa*gr)*cos(bb*gr)+y*cos(aa*gr)*cos(bb*gr)-z*sin(bb*gr);
//координата z
ZZ:=x*sin(aa*gr)*sin(bb*gr)+y*cos(aa*gr)*sin(bb*gr)+z*cos(bb*gr);
end;
//поворот точки вокруг оси оу
procedure GetXYZaroundY(var XX/YY/ZZ:real;x/y/z:real;u:integer);
const
//градус в радианах
gr=pi/i8o;
begin
//координатах
xx:=x*cos(u*gr)-z*sin(u*gr);
//координата у
уу:=у;
//координатах
zz:=x*sin(u*gr)+z*cos(u*gr);
end;
//расчет координат для всех полигонов массива polygons
procedure Get_Polygons;
const
//константы для корректировки координат
сх=о;
су=о;
cz=o.4;
var
//счетчики
ij, k, h integer;
//переменные для расчета координат
xx^zzireal;
xxo/yyo/zzo:real;
xxc/yyc/zzc:real;
xxx/yyy/zzz:real;
323
РАЗРАБОТКА SCADA-СИСТЕМ
//буфер для сортировки массива polygons
buf:t_polygon;
//буфер для сортировки массива mas
bf:byte;
//счетчик
s: integer;
begin
//задание начальных значений
for 1с=о to lms-i do
mas[k]:=l<;
//если угол поворота меньше границы
if uu<=gran then
begin
//порядок от рисовки фигур
mas[7]:=7;
mas[9]:=9;
end
else
begin
//порядок от рисовки фигур
mas[7]:=9;
mas[9]:=7;
end;
//количество элементов массива polygons
I polygons:=o;
//длина динамического массива
SetLength(polygonsz (polygons);
//цикл по всем фигурам
for к:=о to lms-i do
// если фигура видима
if ms[mas[k]].v then
//цикл по всем полигонам массива rets
// mas[k] фигуры
for i:=о to ms[mas[k]].lrcts-i do
with ms[mas[k]].rcts[i] do
begin
//увеличение количества элементов массива
inc(l polygons);
//изменение длины массива
SetLength(polygonsz (polygons);
//цвет полигона
polygons[lpolygons-i].color:=color;
324
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//начальное значение суммы z-координат
polygons[lpolygons-i].total_z:=o;
//координаты центра полигона
xxo:=ms[mas[k]].xo-cx;
yyo:=ms[mas[k]].yo-cy;
zzo:=ms[mas[k]].zo-cz;
//цикл по координатам полигона
for j:=o to з do
begin
//j-координаты полигона
xxx:=xxo+rct[j].x;
yyy:=yy°+rct[j].y;
zzz:=zzo+rct[j].z;
//поворот точки вокруг оси оу на угол и
G etXYZa го и n d Y(xx/yy/ zz, ххх,ууу, zzz, m s [m a s [ k] ]. и);
//j-координаты полигона с учетом
//значений тегов ОРС-сервера
xx:=xx+cx+ms[mas[k]].xc;
yy:=yy+cy+ms[mas[k]].yc;
zz:=zz+cz+ms[mas[k]].zc;
//экранные j-координаты полигона
G etXXYYZZ(xxc,yy с, zzc/xx/yy/zz, a I рh a, beta);
//экранные j-координаты с учетом
//коэффициентов масштабирования
polygons[lpolygons-i].plgn[j].X:=round(xxc*dx)+dx;
polygons[lpolygons-i].plgn[j]Y:=round(yyc*dy)+dy;
// сумма z-координат
polygons[lpolygons-i].total_z:=polygons[lpolygons-i].total_z+zzc;
end;
//замыкание полигона
polygons[l polygons-i]. pig n [4] .X:=polygons[l polygons-i]. plgn [о] .X;
polygons[lpolygons-i].plgn[4]Y:=polygons[lpolygons-i].plgn[o]Y;
end;
//начальное значение счетчика
//номер, с которого начинаются
//полигоны очередной фигуры
s:=o;
//если количество полигонов больше нуля
if lpolygons>i then
//цикл по количеству фигур
for h:=o to lms-i do
// если фигура видима
325
РАЗРАБОТКА SCADA-СИСТЕМ
if ms[mas[h]].v then
begin
//ес/ш количество полигонов больше нуля
if ms[mas[h]].lrcts>i then
//сортировка полигонов
for i:=o to ms[mas[h]].lrcts-i do
forj:=oto ms[mas[h]].lrcts-2 do
// если сумма z-координат s+j элемента
//больше суммы z-координат s+j+i элемента
// то происходит обмен местами этих элементов
if polygons[s+j].total_z>polygons[s+j+i].total_z then
begin
//сохранение полей записи s+j
//в запись buf
with polygons[s+j] do
begin
buf.Color:=Color;
buf.total_z:=total_z;
for lc=o to 4 do
begin
buf.plgn[k].X:=plgn[k].X;
buf.plgn[k].Y:=plgn[k].Y;
end;
end;
//запись s+j+i элемента
//на место s+j
with polygons[s+j] do
begin
color:=polygons[s+j+i].color;
total_z:=polygons[s+j+i].total_z;
for k:=o to 4 do
begin
plgn[k].X:=polygons[s+j+i].plgn[k].X;
plgn[k].Y:=polygons[s+j+i].plgn[k].Y;
end;
end;
//запись s+jэлемента
//на место s+j+i
with polygons[s+j+i] do
begin
Color: = buf.Color;
total_z:=buf.total_z;
326
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
for k:=oto 4 do
begin
plgn[k].X:=buf.plgn[k].X;
plgn[k].Y:=buf.plgn[k].Y;
end;
end;
end;
//вычисление нового значения счетчика
s:=s+ms[mas[h]].lrcts;
end;
end;
//заполнение полей записи ret
procedure Set_Rcts(var rct:t_rct;
Xi/yi/zi/x2/y2/z2/x3/y3/z3/x4/y4/z4:real;clr:integer);
begin
with ret do
begin
//цвет полигона
Со1ог:=с1г;
//координаты полигона
rct[o].x:=xi;
rct[o].y:=yi;
rct[o].z:=zi;
rct[i].x:=X2;
rct[i].y:=y2;
rct[l].z:=Z2;
rct[2].x:=X3;
rct[2].y:=y3;
rct[2].z:=Z3;
rct[3].x:=X4;
rct[3].y:=y4;
rct[3].z:=Z4;
end;
end;
//происходит при создании формы
procedure TMainForm.FormCreate(Sender: TObject);
var
//промежуточная переменная
pnreal;
begin
//инициализация генератора случайных чисел
327
РАЗРАБОТКА SCADA-СИСТЕМ
randomize;
//сохранение текущей директории приложения
CurrDir:=GetCurrentDir+T;
//начальные значения
t5:=false;
ti:=o;
t2:=O;
uu:=min_uu;
//нижнее основание: - о количество элементов
lms:=i;
//длина массива
SetLength(ms,lms);
with ms[lms-i] do
begin
//начальные значения
xo:=o;
yo:=o;
Z0:=-0.2;
XC:=O;
yC:=O;
ZC:=O;
U:=0;
V:=true;
//количество полигонов
I rets:=6;
//длина массива
SetLength(rcts,lrcts);
//левая грань
Set_Rcts(rcts[o]/-oj/ 0.5, 0.05, -0.7,-0.5, 0.05,
-0.7,-о.5,-0.05, -0.7, 0.5, -0.05,
clBlue);
//правая грань
Set_Rcts(rcts[i]/oj/ 0.5, 0.05, о.7,-0.5, 0.05,
0-7/"°-5/"0-°5/ °-7/ 0-5/"°-°5/
clBlue);
//верхняя грань
Set_Rcts(rcts[2]/-oj/ 0.5,0.05, -07,-0.5,0.05,
07,-0.5,0.05, 0.7, 0.5,0.05,
cISkyBlue);
//нижняя грань
Set_Rcts(rcts[3],-o.7, 0.5,-0.05, -0.7,-0.5,-0.05,
0.7,-о.5,-о.05, °-7/ °-5/"°-°5/
cISkyBlue);
328
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//передняя грань
Set_Rcts(rcts[zh]/-o.7/o.5/ 0.05, 07,0.5, 0.05,
07,0.5,-0.05, -07,0.5,-0.05,
cl Blue);
//задняя грань
Set_Rcts(rcts[5],-o.7,-o.5, 0.05, 0.7,-о.5, 0.05,
0-7/"°-5/"0-°5/ -0.7,-о.5,-о.05,
cl Blue);
end;
//верхнее основание: х-1 количество элементов
inc(lms);
//длина массива
SetLength(ms,lms);
with ms[lms-i] do
begin
//начальные значения
xo:=o;
yo:=o;
ZO:=-O.1;
XC:=O;
yC:=O;
ZC:=O;
U:=O;
V:=true;
//количество полигонов
I rets:=6;
//длина массива
SetLength(rcts,lrcts);
//левая грань
Set_Rcts(rcts[o],-o.i5, 0.6, 0.05, -0.15,-0.6, 0.05,
-0.15,-0.6,-0.05, -0.15, 0.6,-0.05,
cl Red);
//правая грань
Set_Rcts(rcts[i],o.i5, 0.6, 0.05, 0.15,-0.6, 0.05,
0.15,-0.6,-0.05, 0.15, 0.6,-0.05,
clRed);
//верхняя грань
Set_Rcts(rcts[2],-o.i5, 0.6,0.05, -0.15,-0.6,0.05,
0.15,-0.6,0.05, 0.15, 0.6,0.05,
clYellow);
//нижняя грань
Set_Rcts(rcts[3],-o.i5, 0.6,-0.05, -0.15,-0.6,-0.05,
0.15,-0.6,-0.05, 0.15, 0.6,-0.05,
329
РАЗРАБОТКА SCADA-СИСТЕМ
cl Maroon);
//передняя грань
Set_Rcts(rcts[zh]/-o.i5/o.6/ 0.05, 0.15,0.6, 0.05,
0.15,0.6,-0.05, -0.15,0.6,-0.05,
cl Red);
//задняя грань
Set_Rcts(rcts[5],-0.15,-0.6, 0.05, 0.15,-0.6, 0.05,
0.15,-0.6,-0.05, -0.15,-0.6,-0.05,
cl Red^-
end;
//основание для «хваталки»: xy- 2 количество элементов
inc(lms);
//длина массива
SetLength(ms,lms);
with ms[lms-i] do
begin
//начальные значения
xo:=o;
yo:=o;
Z0:=0.25;
XC:=O;
yC:=O;
ZC:=O;
U:=O;
v:=true;
//количество полигонов
I rets:=6;
//длина массива
SetLength(rcts,lrcts);
//левая грань
Set_Rcts(rcts[o],-o.i5, 0.05, 0.3, -0.15,-0.05, 0.3,
-0.15,-0.05,-0.3, -0.15, 0.05,-03,
cIGreen);
//правая грань
Set_Rcts(rcts[i],o.i5, 0.05, 0.3, 0.15,-0.05, 0.3,
0.15,-0.05,-03, 0.15, 0.05,-03,
cIGreen);
//верхняя грань
Set_Rcts(rcts[2],-o.i5, 0.05,0.3, -0.15,-0.05,0.3,
0.15,-0.05,0.3, 0.15, 0.05,0.3,
cIGreen);
//нижняя грань
330
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Set_Rcts(rcts[3]/-o.i5/o.O5/ -0.3, -0.15,-0.05,-03,
0.15,-0.05,-03, 0.15, 0.05,-03,
cIGreen);
//передняя грань
Set_Rcts(rcts[4],-o.i5,o.O5, 0.3, 0.15,0.05, 0.3,
0.15,0.05,-0.3, -0.15,0.05,-0.3,
clLime);
//задняя грань
Set_Rcts(rcts[5],-0.15,-0.05, 0.3, 0.15,-0.05, 0.3,
0.15,-0.05,-03, -0.15,-0.05,-03,
clLime);
end;
//центр хваталки: xyz-3 количество элементов
inc(lms);
//длина массива
SetLength(ms,lms);
with ms[lms-i] do
begin
//начальные значения
xo:=o;
yo:=O.O75;
zo:=o.4;
XC:=O;
yC:=O;
ZC:=O;
U:=O;
V:=true;
//количество полигонов
I rets:=4;
//длина массива
SetLength(rcts,lrcts);
//левая грань
Set_Rcts(rcts[o],-0.075, 0.025, 0.05, -0.05,-0.025, 0.05,
-0.05, -0.025,-0.05, -0.075,0.025,-0.05,
cIGreen);
//правая грань
Set_Rcts(rcts[i],o.O75, 0.025, 0.05, 0.05, -0.025, 0.05,
0.05, -0.025,-0.05, 0.075, 0.025,-0.05,
cIGreen);
//верхняя грань
Set_Rcts(rcts[2],-0.075, 0.025,0.05, -0.05, -0.025,0.05,
0.05, -0.025,0.05, 0.075, 0.025,0.05,
cl MoneyGreen);
331
РАЗРАБОТКА SCADA-СИСТЕМ
//нижняя грань
Set_Rcts(rcts[3],-0.075, 0.025,-0.05, -0.05, -0.025,-0.05,
0.05, -0.025,-0.05, 0.075, 0.025,-0.05,
clMoneyGreen);
end;
//левая часть захватного устройства: xyz
//4 количество элементов
inc(lms);
//длина массива
SetLength(ms,lms);
with ms[lms-i] do
begin
//начальные значения
xo:=-0.0875;
уо:=о.25;
zo:=o.4;
ХС:=О;
уС:=О;
ZC:=O;
U:=O;
v:=true;
//количество полигонов
I rets:=4;
//длина массива
SetLength(rcts, Ircts);
//левая грань
Set_Rcts(rcts[o],-o.o875,o.i5, 0.05, 0.01, -0.15, 0.05,
0.01, -0.15,-0.05, -0.0875, 0.15,-0.05,
cIGreen);
//правая грань
Set_Rcts(rcts[i],-0.0125, 0.15, 0.05, 0.0875,-0.15, 0.05,
0.0875,-0.15,-0.05, -0.0125, 0.15,-0.05,
cIGreen);
//верхняя грань
Set_Rcts(rcts[2],-0.0875, 0.15,0.05, 0.01, -0.15,0.05,
0.0875,-0.15,0.05, -0.0125, 0.15,0.05,
clMoneyGreen);
//нижняя грань
Set_Rcts(rcts[3],-0.0875, 0.15,-0.05, 0.01, -0.15,-0.05,
0.0875,-0.15,-0.05, -0.0125, 0.15,-0.05,
clMoneyGreen);
end;
332
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//сжатый левый захват: xyz5
//количество элементов
inc(lms);
//длина массива
SetLength(ms,lms);
with ms[lms-i] do
begin
//начальные значения
xo:=-0.1375;
уо:=о.45;
zo:=o.4;
XC:=O;
yC:=O;
ZC:=O;
U:=O;
v:=not t5;
//количество полигонов
I rets:=5;
//длина массива
SetLength(rcts,lrcts);
//левая грань
Set_Rcts(rcts[o],-0.0375, 0.05, 0.05, -0.0375,-0.05, 0.05,
-0.0375,-0.05,-0.05, -0.0375, 0.05,-0.05,
cIGreen);
//правая грань
Set_Rcts(rcts[i],0.0375, 0.05, 0.05, 0.0375,-0.05, 0.05,
0.0375,-0.05,-0.05, 0.0375, 0.05,-0.05,
cIGreen);
//верхняя грань
Set_Rcts(rcts[2],-0.0375, 0.05,0.05, -0.0375,-0.05,0.05,
о.0375,-о.05,о.05, 0.0375, 0.05,0.05,
cl Money Green);
//нижняя грань
Set_Rcts(rcts[3],-0.0375, 0.05,-0.05, -0.0375,-0.05,-0.05,
0.0375,-0.05,-0.05, 0.0375, 0.05,-0.05,
cl М on еу Green),
//передняя грань
Set_Rcts(rcts[4],-o.O375,o.O5, 0.05, 0.0375,0.05, 0.05,
о.0375,о.05,-о.05, -0.0375,0.05,-0.05,
clOlive);
end;
//разжатый левый захват: xyz -6 количество элементов
inc(lms);
333
РАЗРАБОТКА SCADA-СИСТЕМ
//длина массива
SetLength(ms,lms);
with ms[lms-i] do
begin
//начальные значения
xo:=-o. 15625;
yo-0.45;
ZO:=O.4;
XC:=O;
yC:=O;
ZC:=O;
U:=O;
v:=t5;
//количество полигонов
I rets:=5;
//длина массива
SetLength(rcts,lrcts);
//левая грань
Set_Rcts(rcts[o],-0.0375, 0.05, 0.05, -0.01875,-0.05, 0.05,
-0.01875,-0.05,-0.05, -0.0375, 0.05,-0.05,
cIGreen);
//правая грань
Set_Rcts(rcts[i],o.O375, 0.05, 0.05, 0.05625,-0.05, 0.05,
0.05625,-0.05,-0.05, 0.0375, 0.05,-0.05,
cIGreen);
//верхняя грань
Set_Rcts(rcts[2],-0.0375, 0.05,0.05, -0.01875,-0.05,0.05,
0.05625,-0.05,0.05, 0.0375, 0.05,0.05,
cl MoneyGreen);
//нижняя грань
Set_Rcts(rcts[3],-0.0375, 0.05,-0.05, -0.01875,-0.05,-0.05,
0.05625,-0.05,-0.05, 0.0375, 0.05,-0.05,
clMoneyGreen);
//передняя грань
Set_Rcts(rcts[4],-o.O375,o.O5, 0.05, 0.0375,0.05, 0.05,
0.0375,0.05,-0.05, -0.0375,0.05,-0.05,
clOlive);
end;
//основание бутылки: xyz-y количество элементов
inc(lms);
//длина массива
SetLength(ms,lms);
with ms[lms-i] do
334
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
begin
//начальные значения
хо:=о;
уо:=о.45;
ZO:=O.3;
ХС:=О;
уС:=О;
ZC:=O;
U:=O;
v:=not t5;
//количество полигонов
lrcts:=6;
//длина массива
SetLength(rcts, Ircts);
//левая грань
Set_Rcts(rcts[o],-o.i, 0.05, 0.25, -0.1,-0.05, 0.25,
-о.i,-o.05,-0.25, -0.1, 0.05,-0.25,
clTeal);
//правая грань
Set_Rcts(rcts[i],o.i, 0.05, 0.25, 0.1,-0.05, 0.25,
о.1,-0.05,-0.25, o.i, 0.05,-0.25,
clTeal);
//верхняя грань
Set_Rcts(rcts[2],-o.i, 0.05,0.25, -0.1,-0.05,0.25,
0.1,-0.05,0.25, 0.1, 0.05,0.25,
clTeal);
//нижняя грань
Set_Rcts(rcts[3],-o.i, 0.05,-0.25, -0.1,-0.05,-о.25,
o.i,-0.05,-о.25, o.i, 0.05,-0.25,
clTeal);
//передняя грань
Set_Rcts(rcts[4],-o.i,o.O5, 0.25, 0.1,0.05, 0.25,
0.1,0.05,-0.25, -0.1,0.05,-0.25,
clAqua);
//задняя грань
Set_Rcts(rcts[5],-0.1,-0.05, 0.25, 0.1,-0.05, 0.25,
0.1,-0.05,-о.25, -o.i,-0.05,-о.25,
clAqua);
end;
//горлышко бутылки: xyz-8 количество элементов
inc(lms);
//длина массива
335
РАЗРАБОТКА SCADA-СИСТЕМ
SetLength(ms,lms);
with ms[lms-i] do
begin
//начальные значения
xo:=o;
yo:=o.45;
zo:=o.65;
XC:=O;
yC:=O;
ZC:=O;
U:=O;
v:=not t5;
//количество полигонов
I rets:=6;
//длина массива
SetLength(rcts,lrcts);
// левая грань
Set_Rcts(rcts[o]/-o.O5/ 0.025, 0.1, -0.05,-0.025, 0.1,
-0.05,-0.025,-0.1, -0.05, 0.025,-0.1,
clTeal);
//правая грань
Set_Rcts(rcts[i],o.O5, 0.025, 0.1, 0.05,-0.025, 0.1,
0.05,-0.025,-0.1, 0.05, 0.025,-0.1,
clTeal);
//верхняя грань
Set_Rcts(rcts[2],-o.O5, 0.025,0.1, -0.05,-0.025,0.1,
0.05,-0.025,0.1, 0.05, 0.025,0.1,
clTeal);
//нижняя грань
Set_Rcts(rcts[3],-o.O5, 0.025,-0.1, -0.05,-0.025,-0.1,
0.05,-0.025,-0.1, 0.05, 0.025,-0.1,
clTeal);
//передняя грань
Set_Rcts(rcts[4],-o.O5,o.O25, 0.1, 0.05,0.025, 0.1,
0.05,0.025,-0.1, -0.05,0.025,-0.1,
clAqua);
//задняя грань
Set_Rcts(rcts[5],-0.05,-0.025, 0.1, 0.05,-0.025, 0.1,
0.05,-0.025,-0.1, -0.05,-0.025,-0.1,
clAqua);
end;
//пробка бутылки: xyz-у количество элементов
336
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
inc(lms);
//длина массива
SetLength(ms,lms);
with ms[lms-i] do
begin
//начальные значения
xo:=o;
уо-0.45;
zo:=o.8;
XC:=O;
yC:=O;
ZC:=O;
U:=O;
v:=not t5;
//количество полигонов
lrcts:=6;
//длина массива
SetLength(rcts,lrcts);
//левая грань
Set_Rcts(rcts[o]/-o.O5/ 0.025, 0.05, -0.05,-0.025, 0.05,
-0.05,-0.025,-0.05, -0.05, 0.025,-0.05,
clOlive);
//правая грань
Set_Rcts(rcts[i],o.O5, 0.025, 0.05, 0.05,-0.025, 0.05,
0.05,-0.025,-0.05, 0.05, 0.025,-0.05,
clOlive);
//верхняя грань
Set_Rcts(rcts[2],-o.O5, 0.025,0.05, -0.05,-0.025,0.05,
0.05,-0.025,0.05, 0.05, 0.025,0.05,
clOlive);
//нижняя грань
Set_Rcts(rcts[3],-o.O5, 0.025,-0.05, -0.05,-0.025,-0.05,
0.05,-0.025,-0.05, 0.05, 0.025,-0.05,
clOlive);
//передняя грань
Set_Rcts(rcts[4],-o.O5,o.O25, 0.05, 0.05,0.025, 0.05,
0.05,0.025,-0.05, -0.05,0.025,-0.05,
clYellow);
//задняя грань
Set_Rcts(rcts[5],-0.05,-0.025, 0.05, 0.05,-0.025, 0.05,
0.05,-0.025,-0.05, -0.05,-0.025,-0.05,
clYellow);
end;
337
РАЗРАБОТКА SCADA-СИСТЕМ
//правая часть «хваталки»: xyz-io количество элементов
inc(lms);
//длина массива
SetLength(ms,lms);
with ms[lms-i] do
begin
//начальные значения
xo:=o.o875;
yo:=o.25;
zo:=o.4;
XC:=O;
yC:=O;
ZC:=O;
U:=0;
V:=true;
//количество полигонов
I rets:=4;
//длина массива
SetLength(rcts,lrcts);
//левая грань
Set_Rcts(rcts[o], 0.0875,0.15, 0.05, -0.01, -0.15, 0.05,
-0.01, -0.15,-0.05, 0.0875, 0.15,-0.05,
cIGreen);
//правая грань
Set_Rcts(rcts[i], 0.0125, 0.15, 0.05, -0.0875,-0.15, 0.05,
-0.0875,-0.15,-0.05, 0.0125, 0.15,-0.05,
cIGreen);
//верхняя грань
Set_Rcts(rcts[2],o.o875, 0.15,0.05, -0.01, -0.15,0.05,
-0.0875,-0.15,0.05, 0.0125, 0.15,0.05,
cl MoneyGreen);
//нижняя грань
Set_Rcts(rcts[3], 0.0875, 0.15,-0.05, -0.01, -0.15,-0.05,
-0.0875,-0.15,-0.05, 0.0125, 0.15,-0.05,
clMoneyGreen);
end;
//сжатый правый захват xyz -11 количество элементов
inc(lms);
//длина массива
SetLength(ms,lms);
with ms[lms-i] do
begin
338
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//начальные значения
хо:=0.1375;
уо:=о.45;
zo:=o.4;
ХС:=О;
уС:=О;
ZC:=O;
U:=O;
v:=not t5;
//количество полигонов
Ircts:=5;
//длина массива
Setl_ength(rcts, Ircts);
//левая грань
Set_Rcts(rcts[o],-0.0375, 0.05, 0.05, -0.0375,-0.05, 0.05,
-0.0375,-0.05,-0.05, -0.0375, 0.05,-0.05,
cIGreen);
//правая грань
Set_Rcts(rcts[i],o.O375, 0.05, 0.05, 0.0375,-0.05, 0.05,
0.0375,-0.05,-0.05, 0.0375, 0.05,-0.05,
cIGreen);
//верхняя грань
Set_Rcts(rcts[2],-0.0375, 0.05,0.05, -0.0375,-0.05,0.05,
0.0375,-о.05,о.05, 0.0375, 0.05,0.05,
clMoneyGreen);
//нижняя грань
Set_Rcts(rcts[3],-0.0375, 0.05,-0.05, -0.0375,-0.05,-0.05,
0.0375,-0.05,-0.05, 0.0375, 0.05,-0.05,
clMoneyGreen);
//передняя грань
Set_Rcts(rcts[4],-o.O375,o.O5, 0.05, 0.0375,0.05, 0.05,
о.0375,о.05,-о.05, -0.0375,0.05,-0.05,
clOlive);
end;
//разжатый правый захват xyz-12 количество элементов
inc(lms);
//длина массива
SetLength(ms,lms);
with ms[lms-i] do
begin
//начальные значения
XO:=O. 15625;
339
РАЗРАБОТКА SCADA-СИСТЕМ
УО:=ОЛ5;
ZO:=O.4;
XC:=O;
yC:=O;
ZC:=O;
U:=O;
v:=t5;
//количество полигонов
I rets:=5;
SetLength(rcts,lrcts);
// левая грань
Set_Rcts(rcts[o]/o.O375/ 0.05, 0.05, 0.01875,-0.05, 0.05,
0.01875,-0.05,-0.05, 0.0375, 0.05,-0.05,
cIGreen);
//правая грань
Set_Rcts(rcts[i],-0.0375, 0.05, 0.05, -0.05625,-0.05, 0.05,
-0.05625,-0.05,-0.05, -0.0375, 0.05,-0.05,
cIGreen);
//верхняя грань
Set_Rcts(rcts[2],0.0375, 0.05,0.05, 0.01875,-0.05,0.05,
-0.05625,-0.05,0.05, -0.0375, 0.05,0.05,
clMoneyGreen);
//нижняя грань
Set_Rcts(rcts[3],o.O375, 0.05,-0.05, 0.01875,-0.05,-0.05,
-0.05625,-0.05,-0.05, -0.0375, 0.05,-0.05,
clMoneyGreen);
//передняя грань
Set_Rcts(rcts[4],o.O375,o.O5, 0.05, -0.0375,0.05, 0.05,
-0.0375,0.05,-0.05, 0.0375,0.05,-0.05,
clOlive);
end;
//интервал работы
Timeri. Interval:=юо;
//запрещение работы
Timeri. Enabled :=false;
//интервал работы
Timer2. Interval :=round(time_rotation/max_uu);
//запрещение работы
Timer2. Enabled :=false;
//интервал работы
Timer3. Interval :=round(time_rotation/max_uu);
//запрещение работы
340
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
Timer3. Enabled :=false;
//длина массива
SetLength(mas/lms);
with MainForm do
begin
pr:=ioo;
//ширина формы
Width :=round(Monitor.Width/ioo*pr);
pr:=ioo;
//высота формы
Height:=round(Monitor.Height/ioo*pr);
pr:=o;
//абсцисса левого верхнего угла
Left:=round(Monitor.Width/ioo*pr);
pr:=O;
//ордината левого верхнего угла
Top:=round(Monitor.Height/ioo*pr);
//стиль границ
BorderStyle:=bsNone;
end;
//создание компонента
lmg:=Tlmage.Create(Self);
with Img do
begin
//родитель компонента
Parent:=Self;
pr:=o;
//абсцисса левого верхнего угла
Left:=round(Monitor.Width/ioo*pr);
pr:=O;
//ордината левого верхнего угла
Top:=round(Monitor.Height/ioo*pr);
pr:=ioo;
//ширина
Width :=round(Monitor.Width/ioo*pr);
pr:=ioo;
//высота
Height:=round(Monitor.Height/ioo*pr);
end;
//коэффициенты масштабирования
dx:=lmg.Width div 2;
dy:=lmg.Height div 2;
341
РАЗРАБОТКА SCADA-СИСТЕМ
//область отрисовка графики
r:=Rect(lmg. Left, Img. Top, Img. Width, Img. Height);
//цвет заливки
Img.Canvas. Brush.Colored White;
//заливка области
Img.Canvas. Fill Rect(R);
//координаты плоскости проецирования
alpha:=27;
beta:=70;
end;
//происходит при нажатии клавиши на форме
procedure TMainForm. FormKeyPress(Sender: TObject; var Key: Char);
begin
// если нажата клавиша Esc
if key=#27 then
//закрытие формы
MainForm.Close;
end;
//происходит через определенный интервал времени
procedure TMainForm.TimenTimer(Sender: TObject);
const
//минимальная граница перемещения
//по нижнему основанию
min_ti_xyz=o.5;
//максимальная граница перемещения
//по нижнему основанию
max_ti_xyz=-o.2;
//минимальная граница перемещения
//по верхнему основанию
min_t2_xyz=-o.5;
//максимальная граница перемещения
//по верхнему основанию
max_t2_xyz=o.5;
var
//минимальное значение тега
m in_ti: integer;
//максимальное значение тега
m ax_ti: integer;
//минимальное значение тега
m in_t2: integer;
342
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
//максимальное значение тега
max_t2 integer;
i:integer;
begin
//задание значений
min_ti:=o;
max_ti:=45O;
min_t2:=o;
max_t2:=i2i;
// перемещение no нижнему основанию
ti:=StrTolnt(ltems[o], ItemValue);
//перемещение no верхнему основанию
t2:=StrTolnt(ltems[i]. ItemValue);
//нижний датчик
//угол loo градусов
//true-датчик не сработал
//false-датчик сработал
t3:=StrToBool(ltems[2]. Item Value);
//верхний датчик
//угол о градусов
//true-датчик не сработал
//false-датчик сработал
t4:=StrToBool(ltems[3]. Item Value);
//деталь
// true — детали нет
//false — деталь есть
t5:=StrToBool(ltems[4]. Item Value);
if max_ti>=min_ti then
//перемещение no нижнему основанию
tti:=((ti*ioo/abs(max_ti-min_ti))*(max_ti_xyz-min_ti_xyz)/ioo)-
(max_ti_xyz-min_ti_xyz)/2
else
//перемещение no нижнему основанию
tti:=(ioo-(ti*ioo/abs(max_ti-min_ti))*(max_ti_xyz-min_ti_xyz)/ioo)-
(max_ti_xyz-min_ti_xyz)/2;
//если количество фигур больиие нуля
if lms>i then
//цикл no количеству фигур
for i:=i to Ims-i do
//перемещение no нижнему основанию
ms[i].xc:=tti;
if max_t2>=min_t2 then
343
РАЗРАБОТКА SCADA-СИСТЕМ
//перемещение по верхнему основанию
tt2:=((t2*ioo/abs(max_t2-min_t2))*(max_t2_xyz-min_t2_xyz)/ioo)-
(max_t2_xyz-min_t2_xyz)/2
else
//перемещение по верхнему основанию
tt2:^ioo-(t2*ioo/abs(max_t2-min_t2))*(max_t2_xyz-min_t2_xyz)/ioo)-
(max_t2_xyz-min_t2_xyz)/2;
//если количество фигур больше нуля
if lms>i then
//цикл по количеству фигур
for i:=2 to lms-i do
//перемещение no верхнему основанию
ms[i].yc:=tt2;
//видимость фигур
ms[5].v:=not t5;
ms[6].v:=t5;
ms[7].v:=not t5;
ms[8].v:=not t5;
ms[9].v:=not t5;
ms[n].v:=not t5;
ms[i2].v:=t5;
//цикл no количеству фигур
for i:=з to lms-i do
//угол поворота фигуры
ms[i].u:=uu;
//если сработал нижний датчик
if not t3 then
begin
//разрешение работы таймера
Timer2.Enabled:=true;
//запрещение работы таймера
Timer3.Enabled:=false;
//угол наклона
ии:=тах_ии;
end;
//если сработал верхний датчик
if not t4 then
begin
//запрещение работы таймера
Timer2.Enabled:=false;
//разрешение работы таймера
Timer3.Enabled:=true;
344
ГЛАВА 2. Организация взаимодействия программного обеспечения диспетчерского ...
IIугол наклона
uu:=min_uu;
end;
II получение полигонов
Get_Polygons;
IIстиль заливки
Img. Canvas. Brush. Style:=bsSol id;
II цвет заливки
Img.Canvas. Brush.Colored White;
IIзаливка области
Img.Canvas. Fill Rect(R);
II цикл no количеству полигонов
for i:=oto lpolygons-i do
begin
II цвет заливки
Img.Canvas. Brush.Color:=polygons[i].color;
II цвет линий
Img.Canvas. Pen.Color:=polygons[i].color;
II отрисовка полигона
Img.Canvas. Polygon(polygons[i].plgn);
end;
end;
II происходит при показе формы
procedure TMainForm.FormShow(Sender: TObject);
begin
IIразрешение работы таймера
Timeri. Enabled :=true;
end;
II происходит при закрытии формы
procedure TMainForm.FormClose(Sender: TObject;
var Action: TCIoseAction);
begin
IIзапрещение работы таймера
Timeri. Enabled:=false;
end;
II происходит через определенный интервал времени
procedure TMainForm.Timer2Timer(Sender: TObject);
begin
IIуменьшение значения угла наклона
dec(uu);
345
РАЗРАБОТКА SCADA-СИСТЕМ
И если угол наклона меньше минимального значения
if uu<=min_uu then
//запрещение работы таймера
Timer2.Enabled:=false;
end;
//происходит через определенный интервал времени
procedure TMainForm.Timer3Timer(Sender: TObject);
begin
//увеличение значения угла наклона
inc(uu);
//если угол наклона больше максимального значения
if uu>=max_uu then
//запрещение работы таймера
Timer3. Enabled :=false;
end;
end.
346
ГЛАВА 3.
Организация взаимодействия
программного обеспечения компьютеров
диспетчерского уровня
распределенной системы управления
3.1. Структура компьютерной распределенной системы
управления с многоузловым диспетчерским уровнем
Аппаратные средства КРСУ
Структурная схема КРСУ приведена на рис. 3.1. Удаленные
компьютеры (рабочие станции) КРСУ, образующие диспетчерский
уровень, показаны в левой части рис. 3.1. В правой части рис. 3.1
расположен контроллерный уровень КРСУ.
Все контроллеры можно организационно разбить на ряд сег-
ментов. На рис. 3.1 таких сегментов ш. Каждый сегмент может со-
держать до 256 контроллеров с адресами от 00 до FF в шестнадца-
тиричной системе счисления. Каждый контроллер промышленной
сети содержит свою индивидуальную управляющую программу
контроллера (УПК) и обслуживает определенное количество испол-
нительных механизмов (ИМ) и датчиков (Д).
На рис. 3.1 показано подключение к контроллеру с адресом FE
из сегмента с номером 1 нескольких исполнительных механизмов
ИМ7.. . ИМА и нескольких датчиков Д7.. .ДУ
Контроллер принимает информацию с датчиков, логически и
математически ее обрабатывает. На основании полученных резуль-
татов он подготавливает управляющие воздействия и отправляет их
на исполнительные механизмы. Так формируется контур управления.
Один контроллер может обслуживать несколько независимых
контуров управления, но, с другой стороны, один контур управле-
ния может обслуживаться несколькими контроллерами совместно.
Это бывает в том случае, если аппаратных средств или памяти од-
ного контроллера не хватает на решение задачи управления конту-
ром. В этом случае необходима связь между несколькими контрол-
лерами, что реализуется с помощью промышленной сети (полевой
шины), например, на основе стандарта RS-485.
347
РАЗРАБОТКА SCADA-СИСТЕМ
Однако промышленная сеть нужна не только для соединения
контроллеров РСУ между собой, но и для связи контроллеров ниж-
него контроллерного уровня с удаленными компьютерами диспет-
черского уровня.
Для связи контроллерного и диспетчерского уровней выделя-
ется один из компьютеров диспетчерского уровня. Такой компью-
тер называется мастером (master) сети. Через него информация
с контроллеров контроллерного уровня КРСУ может передаваться
на компьютеры (slave) диспетчерского уровня. Естественно, что
компьютеры диспетчерского уровня тоже должны быть объединены
в сеть. Это может быть, например, сеть Ethernet с протоколом пе-
редачи данных TCP/IP.
Таким образом, мастер является связующим звеном между
контроллерами и компьютерами диспетчерского уровня.
Программные средства КРСУ
Из рис. 3.1 видно, какие программные компоненты должны
быть расположены на мастере и на удаленных компьютерах
диспетчерского уровня.
Программное обеспечение компьютеров диспетчерского
уровня реализовано в виде ОРС-клиентов — приложений, способ-
ных взаимодействовать по сети Ethernet с ОРС-сервером, распо-
ложенным на мастере. ОРС-клиенты, связываясь с ОРС-сервером,
имеют возможность чтения информации с контроллеров, подклю-
ченных к промышленной сети PLCNet. Кроме этого, ОРС-клиент
может логически и математически обрабатывать полученную из
контроллеров информацию и выводить результаты на экран уда-
ленного компьютера диспетчерского уровня в нужной форме,
т. е. выполнять функции SCADA-системы. К локальной сети
Ethernet может быть подключено произвольное число удаленных
компьютеров. Результаты работы распределенной системы управ-
ления технологическим оборудованием могут передаваться на
любое число этих компьютеров. Важно, чтобы на каждом из них
работал ОРС-клиент. ОРС-клиенты, расположенные на компьюте-
рах диспетчерского уровня КРСУ, могут быть совершенно разны-
ми приложениями (SCADA-системами) и выполнять различные
задачи:
348
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
- общая информация о ходе технологического процесса;
- информация о состоянии технологического оборудования;
- информация об аварийных и предаварийных ситуациях;
- информация о выполнении плановых показателей;
- архивирование информации об основных технологических
параметрах и т. д.
Программное обеспечение мастера, как это следует из рис. 3.1,
содержит три компонента.
1. Fastwel PLCNet ОРС Server, являющийся ОРС-сервером
для узлов сети PLCNet, УПК которых созданы с помощью
системы программирования UltraLogik и объединены с
помощью интерфейса RS-485 или через стандартную сеть
Ethernet с помощью протокола IPX/SPX (IPXNet). Этот
сервер позволяет осуществить обмен данными между узлами
сетей PLCNet ИЛИ IPXNet и приложениями — клиентами
ОРС-сервера.
2. Объект автоматизации (ОА) — приложение, отвечающее
за связь Fastwel PLCNet ОРС Server и ОРС-клиентов,
расположенных на удаленных компьютерах диспетчерского
уровня.
3. Borland Socket Server — утилита, входящая в состав всех
версий Delphi, начиная с 3.01. Она представляет собой
универсальный ОРС-клиент (файл scktsrvr.exe в каталоге
Delphi\Bin). Версии этого приложения, входившие в состав
Delphi 3 и 4, будучи запущенными на каком-либо компьютере,
позволяли осуществить доступ к любым ОРС-серверам
с любого удаленного компьютера, который мог обращаться
к данному компьютеру по протоколу TCP/IP, не только через
локальную сеть, но и через Интернет. При этом, естествен-
но, к компьютеру, содержащему клиентское приложение,
не предъявлялось практически никаких требований, кроме
поддержки протокола TCP/IP и возможности доступа
по указанному порту к компьютеру, содержащему Socket
Server.
349
Рис. 3.1. Программные компоненты КРСУ
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Версии Borland Socket Server, входящие в состав Delphi 5
и выше, были слегка усовершенствованы. Эти приложения можно
запускать в двух режимах:
- предоставления доступа ко всем ОРС-серверам, как в преж-
них версиях Socket Server,
- предоставления доступа к ограниченному набору серверов,
специальным образом зарегистрированных в реестре.
Загрузить Socket Server можно двумя способами.
1. Как исполняемый файл, запустив исполняемый файл
scktsrvr.exe из каталога Delphi\Bin,
2. Зарегистрировать его как сервис серверной ОС Windows
с помощью команды scktsrvr.exe/install. После запуска на
панели задач появится соответствующая кнопка, при щелчке
на которой открывается окно приложения Socket Server.
С помощью окна этого приложения можно указывать номера
портов, по которым следует вести обмен данными с удаленными
клиентами, а также управлять доступом к ОРС-серверам. Режим
доступа можно задать, установив или сняв галочку у команды-
переключателя Registered Objects Only в меню Connections. При
изменении режима доступа Socket Server следует перезапустить.
Borland Socket Server в отличие от DCOM не требует никаких
клиентских частей и дополнительных настроек на рабочих станциях.
Как универсальный ОРС-клиент это и подобные ему приложе-
ния идеальны для удаленного доступа к серверам автоматизации
через Интернет или с использованием технологий, применяемых
в Интернете.
Принцип доступа к ОРС-серверу по протоколу TCP/IP можно
кратко сформулировать следующим образом. Доступ к ОРС-серверу
возможен со всех удаленных компьютеров, имеющих доступ по
протоколу TCP/IP через указанный порт при условии, что на этом
компьютере запущено приложение Socket Server или эквивалент-
ный ему по функциональности ОРС-клиент, и настройки этого
клиента позволяют осуществлять удаленный доступ к данному
серверу.
В разделе 3.2 будет показан пример построения ОА, а в раз-
деле 3.3 — ОРС-клиента, содержащего компоненты, обеспечиваю-
щие его взаимодействие с ОА мастера.
351
РАЗРАБОТКА SCADA-СИСТЕМ
3.2. Назначение и организация объекта автоматизации
Объект автоматизации (ОА) представляет собой приложе-
ние, которое служит для обмена данными между ОРС-сервером
и ОРС-клиентами. Проект ОА состоит из трех модулей: AddUnit,
MainUnit и NDgrServerTLB. Модуль AddUnit представляет
собой обычный модуль, в котором происходит чтение данных
с ОРС-сервера. Модули MainUnit и NDgrServerTLB предна-
значены для обмена данными с ОРС-клиентом, причем модуль
NDgrServerTLB генерируется автоматически средой разработки
Delphi.
3.2.1. Модуль AddUnit
Создание проекта
1. Создадим новый проект: File—>New—> Application.
2. Сохраним проект под именем NDgrServer, а модуль —
как AddUnit. Форму переименуем в AddForm.
3. Добавим в раздел используемых модулей модули OPCDA,
OPCTypes и OPCUtils, при помощи которых и происходит
обмен данными между ОРС-сервером и ОА.
Описание компонентов и процедур — обработчиков событий
1. Компонент Timerl: TTimer предназначен для задания опре-
деленных временных интервалов чтения значений тегов из
ОРС-сервера.
2. В процедуре FormCreate происходит инициализация на-
чальных значений некоторых переменных.
3. В процедуре TimerITimer происходит чтение значение те-
гов из ОРС-сервера.
4. В процедуре FormClose происходит уничтожение динами-
ческих массивов.
Объявление пользовательских процедур и функций
1. Функция GetltemType возвращает тип тега в виде строки.
Тип тега определяется по его значению.
2. Процедура AddServer необходима для запуска ОРС-
сервера, заданного переменной Value.
352
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
3. Процедура AddSegment добавляет сегмент в ОРС-сервер.
4. В процедуре Addltem происходит добавление тега в ОРС-
сервер.
Раздел описания глобальных переменных
1. AddForm — основная форма проекта.
2. Items — одномерный массив записей тегов со следующими
полями:
- ItemName: string — имя тега;
- ItemHandle: OPCHANDLE — уникальный числовой
идентификатор тега (генерируется автоматически):
- ItemType: TVarType — тип тега;
- ItemValue: string — значение тега;
- ItemQuality:Word — качество принятого тега;
- Segments — номер сегмента в массиве Sgmt, в который
добавлен тег.
3. Sgmt — массив записей сегментов со следующими полями:
- Segment: lOPCItemMgt — интерфейс с помощью кото-
рого осуществляется добавление и удаление тегов в сег-
мент;
- SegmentHandle: OPCHANDLE — уникальный число-
вой идентификатор сегмента;
- Sgt: string — имя сегмента.
4. ns: integer — количество сегментов.
5. n: integer — количество тегов.
6. error: boolean — признак ошибки последней операции.
7. Server_Enabled: boolean — признак занятости сервера ав-
томатизации.
8. Itms: WideString — значения тегов.
9. ItmsExists: WideString — имена тегов.
10. SegmentsExists — имена сегментов.
11. Server — интерфейс для связи с ОРС-сервером.
Структуры динамических массивов Sgmt и Items показаны
на рис. 3.2.
353
РАЗРАБОТКА SCADA-СИСТЕМ
Динамический массив Sgmt Динамический массив Items тегов
Sgmt [0] Segment: lOPCItemMgt
SegmentHandle: OPCHandle
Sgt: String
Items [0] ItemName: String
ItemHandle: OPCHandle
ItemType: TVarType
ItemValue: String
ItemQuality: Word
Segments: integer
Sgmt [ns-1] Segment: lOPCItemMgt
SegmentHandle: OPCHandle
Sgt: String
Items [n-1] ItemName: String
ItemHandle: OPCHandle
ItemType: TVarType
ItemValue: String
ItemQuality: Word
Segments: integer
Рис. 3.2. Структуры динамических массивов Sgmt и Items
Пользовательские процедуры и функции
1. Функция GetltemType возвращает в строковом виде тип
тега ItemValue, представленного в строковом виде. Алго-
ритм функции приведен на рис. 3.3.
354
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Рис. 3.3. Алгоритм функции GetltemType (начало)
355
РАЗРАБОТКА SCADA-СИСТЕМ
Функция Getltem Type
Рис. 3.3. Алгоритм функции GetltemType (окончание)
356
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
2. Процедура AddServer запускает ОРС-сервер, заданный зна-
чением Value (например, Value=’FastweLPLCNetOPC’).
Алгоритм процедуры приведен на рис. 3.4. При этом выпол-
няются следующие действия:
- Переменная Server_Enabled принимает значение false
для того, чтобы ОРС-клиенты не могли работать с ОРС-
сервером при выполнении этой процедуры;
- Задается начальное значение false переменной error;
- При помощи функции CreateCOMObject запускается
ОРС-сервер. Если по каким то причинам ОРС-сервер не
запустился, то в переменную error записывается значе-
ние true;
- Переменная Server_Enabled принимает значение true
для того, чтобы ОРС-клиенты могли работать с объектом
автоматизации.
357
РАЗРАБОТКА SCADA-СИСТЕМ
Процедура AddServer
Лист 1
Всего 1
Рис. ЗА. Алгоритм процедуры AddServer
358
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
3. Процедура AddSegment добавляет сегмент, заданный значе-
нием Value (например, Value=’UltraNet_l’) в ОРС-сервер.
Алгоритм процедуры приведен на рис. 3.5. При этом выпол-
няются следующие действия:
- Переменная Server_Enabled принимает значение false
для того, чтобы ОРС-клиенты не могли работать с ОРС-
сервером при выполнении этой процедуры;
- Задается начальное значение false переменной error;
- Запрещается работа таймера Timeri;
- Увеличивается на единицу переменная ns — количество
сегментов;
- Увеличивается на 1 длина динамического массива Sgmt;
- Полю Sgt последнего элемента массива Sgmt присваи-
вается значение Value;
- При помощи функции ServerAddGroup сегмент добав-
ляется в ОРС-сервер;
- Если сегмент добавлен в ОРС-сервер, то к значению
переменной SegmentsExists добавляется значение Value
и пробел. В противном случае переменной error прис-
ваивается значение true, переменная ns уменьшается на
единицу и уменьшается на 1 длина динамического масси-
ва Sgmt,
- Если ранее в ОРС-сервер был добавлен хотя бы один тег,
то разрешается работа таймера Timeri;
- Переменной Server_Enabled присваивается значение
true для доступа к объекту автоматизации ОРС-клиентов;
359
РАЗРАБОТКА SCADA-СИСТЕМ
Процедура AddSegment
Рис. 3.5. Алгоритм процедуры AddSegment
360
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
4. Процедура Addltem добавляет в сегмент Segment тег, за-
данный значением Value. Алгоритм процедуры приведен
на рис. 3.6. При этом выполняются следующие действия:
- Переменная Server_Enabled принимает значение false
для того, чтобы ОРС-клиенты не могли работать с ОРС-
сервером при выполнении этой процедуры.
- Задается начальное значение false переменной error.
- Запрещается работа таймера Timeri.
- Увеличивается на единицу переменная п — количество
тегов.
- Изменяется длина динамического массива Items.
- Полю ItemName последнего элемента массива Items
присваивается значение Value.
- Полю ItemValue последнего элемента массива Items
присваивается начальное значение.
- Происходит поиск сегмента Segment в массиве Sgmt.
Номер найденного сегмента сохраняется в поле Segments
последнего элемента массива Items.
- При помощи функции GroupAddltem тег добавляется
в сегмент Segment.
- Если тег добавился в сегмент, то к значению переменной
ItemsExists добавляется значение Value и пробел. В про-
тивном случае переменной error присваивается значение
true, переменная п уменьшается на единицу и изменяется
длина динамического массива Items.
- Если ранее в ОРС-сервер был добавлен хотя бы один тег,
то разрешается работа таймера Timeri.
- Переменной Server_Enabled присваивается значение
true для доступа к объекту автоматизации ОРС-клиентов.
361
РАЗРАБОТКА SCADA-СИСТЕМ
Процедура Additem
Лист 1
Рис. 3.6. Алгоритм процедуры Additem (начало)
362
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Рис. 3.6. Алгоритм процедуры Additem (окончание)
363
РАЗРАБОТКА SCADA-СИСТЕМ
Процедуры — обработчики событий
1. В процедуре FormCreate происходит задание начальных зна-
чений некоторых переменных. Алгоритм процедуры приведен
на рис. 3.7. При этом выполняются следующие действия:
- Запрещается работа таймера Timerl.
- Задается интервал Interval таймера Time.
-Задается начальное значение количества тегов и сег-
ментов.
- Задаются начальные значения переменных Server, Error,
Itms, SegmentsExists, и ItemsExists.
-Значение переменной Server_Enabled устанавливается
в true.
Процедура FormCreate
Лист 1
Всего 1
Начало
I. Запрещение работы таймера.
2. Установка интервала таймера.
3. Задание начальных значений переменных: п (количество тегов), ns
(число сегментов), Server, Error, Itms, SegmentsExists, ItemsExists.
4. Разрешение работы с ОРС-сервером.
Конец
Рис. 3.7. Алгоритм процедуры FormCreate
2. В процедуре TimerlTimer происходит считывание зна-
чений тегов из ОРС-сервера в динамический массив Items.
Алгоритм процедуры приведен на рис. 3.8. При этом выпол-
няются следующие действия:
- Если ранее в динамический массив Items не было добавлено
ни одного тега, то происходит выход из процедуры.
- Задается начальное значение переменной Itms.
- Происходит чтение значений тегов с помощью функции
ReadOPCGroupItemValue в массив Items. Если прочитали
значение тега без ошибки, а тип тега — Float, то происходит
округление значения тега.
364
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
- К значению переменной Newltems добавляется значение
тега и пробел.
- Значению переменной Itms присваивается значение Newltms.
Процедура TimeriTimer
Рис. 3.8. Алгоритм процедуры TimeriTimer (начало)
365
РАЗРАБОТКА SCADA-СИСТЕМ
Процедура Timeri Timer
Рис. 3.8. Алгоритм процедуры TimeriTimer (окончание)
366
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
3. В процедуре FormClose происходит изменение длин динами-
ческих массивов Items и Sgmt. Алгоритм процедуры при-
веден на рис. 3.9.
Процедура FormClose Лист 1
----Всего 1
( Начало )
1. Изменение длины динамического массива Items.
2. Изменение длины динамического массива Sgmt.
( Конец j
Рис. 3.9. Алгоритм процедуры FormClose
Программный код модуля AddUnit приведен в листинге 3.1.
Листинг 3.1
unit AddUnit;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
Forms,
Dialogs, ExtCtrls, OPCDA, OPCTypes, OPCUtils, ComObj, ActiveX;
type
TAddForm = class(TForm)
//таймер
Timeri: TTimer;
//действия при создании формы
procedure FormCreate(Sender: TObject);
//реакция на сигналы таймера
procedure TimenTimer(Sender: TObject);
//действия при закрытии формы
procedure FormClose(Sender:TObject; var Action: TCIoseAction);
private
{Private declarations}
367
РАЗРАБОТКА SCADA-СИСТЕМ
public
{Public declarations}
end;
//возвращает тип тега no его значению
function GetltemType(ltemValue:string):string;
//запуск заданного ОРС-сервера
procedure AddServer(Value:string);
//добавление заданного сегмента в ОРС-сервер
procedure AddSegment(Value:string);
//добавление заданного тега в ОРС-сервер
procedure Addltem(Value:string;Segment:string);
var
// форма
AddForm: TAddForm;
//массив тегов
ltems:array of record
//имя тега
I te mN a me: st ring;
//хэндл тега
ltemHandle:OPCHANDLE;
//тип тега
ltemType:TVarType;
//значение тега
ltemValue:string;
//качество принятого тега
ltemQuality:word;
//номер сегмента в массиве Sgmt, в который добавлен тег
Segments:integer;
end;
//массив сегментов
Sgmt:array of record
//интерфейс, с помощью которого осуществляется
//добавление тегов в сегмент
SegmentdOPCItemMgt;
//хэндл сегмента
SegmentHandle:OPCHANDLE;
// имя сегмента
Sgt:string;
end;
368
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
//количество сегментов
ns:integer;
//количество тегов
n: integer;
//признак ошибки
Error:boolean;
//признак занятости объекта автоматизации
Server_Enabled:boolean;
//значения тегов
Itms: WideString;
//имена тегов
ltemsExists:WideString;
//имена сегментов
SegmentsExists: WideString;
//интерфейс для связи с ОРС-сервером
Server: lOPCServer;
implementation
{$R *.dfm}
//возвращает тип тега по его значению
function GetltemType(ltemValue:string):string;
var
//счетчики
i,s:byte;
begin
//начальный результат функции
Result:='Timer';
//если значение тега TRUE или FALSE
if (UpperCase(ltemValue)=/TRUE/) or
(UpperCase(ltemValue) ='FALSE') then
begin
//тег имеет тип Boolean
Result:='Boolean';
//выход из функции
exit;
end;
//проверка всех символов значения тега
for i:=i to Length(ltemValue) do
// если нашли точку или запятую
if (ltemValue[i]=7) or (ItemVaIue[i]then
begin
369
РАЗРАБОТКА SCADA-СИСТЕМ
И тег имеет тип Real
Resu It:=Ъ1 oat';
//выход из функции
exit;
end;
//начальное значение счетчика
s:=o;
//проверка всех символов значения тега
for i:=i to Length(ltemValue) do
// если нашли цифру или знак плюс или минус
if ltemValue[i] in [чо717273//Ч75///67778797"7+/] then
//увеличиваем значение счетчика
inc(s);
//если значение счетчика совпадает
//с количеством символов значения тега
if s=l_ength(ltemValue) then
begin
//тег имеет тип Integer
Resu It:='l nteger';
//выход из процедуры
exit;
end;
end;
//запускает заданный значением Value ОРС-сервер
procedure AddServer(Value: string);
begin
//доступ запрещен
Server_Enabled:=false;
//начальное значение переменной
Error: =fa Ise;
// если ОРС-сервер не запущен
if Server=nil then
try
//создание сервера
Server:=CreateComObject(ProglDToClasslD(Value))
as lOPCServer;
// если не смогли создать сервер
except
Error:=true;
//уничтожение сервера
Server:=nil;
370
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
end;
// доступ разрешен
Server_Enabled:=true;
end;
//добавление заданного сегмента в массив Sgmt
procedure AddSegment(Value: string);
var
HR:HRESULT;
begin
//доступ запрещен
Server_Enabled:=false;
//начальное значение переменной
Error: =fa Ise;
//запрет работы таймера
Add Form .Timen. Enabled :=false;
//увеличение количества сегментов
inc(ns);
//изменение длины массива сегментов
SetLength(Sgmt,ns);
//имя последнего элемента в массиве Sgmt
Sgmt[ns-i].Sgt:=Value;
//добавление сегмента в массив Sgmt
HR:=ServerAddGroup(Server,Sgmt[ns-i].Sgt,true,5OO,o,
Sgmt[ns-i].Segment,Sgmt[ns-i].SegmentHandle);
//если произошла ошибка
if Failed(HR) then
begin
Error:=true;
//уменьшение количества сегментов на i
Dec(ns);
//изменение длины динамического массива
SetLength(Sgmt,ns);
end
else
//добавление имени очередного сегмента к именам
//существующих сегментов
SegmentsExists:=SegmentsExists+Value+#32;
// если был добавлен хотя бы один тег
if noo then
//работа таймера разрешена
Add Form .Timen. Enabled :=true;
371
РАЗРАБОТКА SCADA-СИСТЕМ
//доступ разрешен
Server_Enabled:=true;
end;
//добавление заданного тега в массив тегов Items
procedure Addltem(Value:string;Segment:string);
var
HR:HRESULT;
//счетчик
i:integer;
begin
//доступ запрещен
Server_Enabled:=false;
//начальное значение
Error: =fa Ise;
//запрет работы таймера
Add Form .Timeri. Enabled :=false;
//увеличение количества тегов
lnc(n);
//изменение длины массива тегов
SetLength(ltems,n);
//имя последнего элемента в массиве тегов
ltems[n-i].ltemName:=Value;
//значение последнего элемента в массиве тегов
Itemsfn-iJ.ltemValue^'o';
for i:=o to ns-i do
//если в массиве Sgmt найден сегмент,
// в который добавляется тег
if Segment=Sgmt[i].Sgt then
//запоминаем номер сегмента
ltems[n-i].Segments:=i;
//добавление тега
HR:=GroupAddltem(Sgmt[ltems[n-i]. Segments]. Segment,
ltems[n-i]. Item Name,Sgmt[ltems[n-i].Segments].SegmentHandle,
VT_EM PTY, ltems[n-i]. Item Handle, ltems[n-i]. ItemType);
//если произошла ошибка
if Failed(HR) then
begin
//уменьшение количества тегов
Dec(n);
//изменение длины динамического массива Items
SetLength(ltems,n);
372
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Error:=true;
end
else
//добавление имени очередного тега
// к именам существующих тегов
ltemsExists:=ltemsExists+Value+#32;
// если в Items был добавлен хотя бы один тег
if noo then
//работа таймера разрешена
Add Form. Timeri. Ena bled: =true;
// доступ к серверу разрешен
Server_Enabled:=true;
end;
//задание начальных значений, переменных
procedure TAddForm. FormCreate(Sender: TObject);
begin
//работа таймера запрещена
Timeri. Enabled :=false;
//интервал работы таймера
Ti men. Interval:=юо;
//начальное значение количества тегов
п:=о;
//начальное значение количества сегментов
ns:=o;
//начальное значение
Server:=nil;
//начальное значение ОРС-сервер выключен
Error: =fa Ise;
//начальное значение строки значений тегов
ltms:=";
//начальное значение строки имен сегментов
SegmentsExists:=";
//начальное значение строки имен тегов
I terns Exists
//доступ разрешен
Server_Enabled:=true;
end;
//чтение значений тегов из ОРС-сервера
procedure TAddForm.TimenTimer(Sender: TObject);
var
373
РАЗРАБОТКА SCADA-СИСТЕМ
//счетчик
i:integer;
HR:HRESULT;
//значения тегов, расположенные в одной строке через пробел
Newltms: WideString;
begin
// если нет добавленных тегов
if n=othen
//выход из процедуры
exit;
//начальное значение строки значений
Newltms:=";
//чтение значений тегов из ОРС-сервера
for i:=o to n-i do
begin
//чтение из сегмента Segment значения и качества связи
// тегов с хэндлом Item Handle в поля ItemValue и ItemQuality
HR:=ReadOPCGroupltem Vai ue(Sgmt[ltems[i]. Segments]. Segment,
ltems[i]. Item Handle, ltems[i]. Item Value, ltems[i]. ItemQuality);
// если прочитали без ошибок
if Succeeded(HR) then
//если тип тега 'Float'
if GetltemType(ltems[i].ltemValue)=/Float/then
begin
//если значение тега меньше одной тысячной
if StrToFloat(ltems[i].ltemValue)<o.ooi then
//значение тега
ltems[i].ltemValue:='o';
//округление значения тега
ltems[i]. Item Value:=FloatToStrF(StrToFloat(ltems[i]. Item Value),
fffixed,5,3);
end;
// если произошла ошибка
if Failed(HR) then
//значение тега
ltems[i].ltemValue:='o';
//добавление значения нового тега в строку значений тегов
Newltms:=Newltms+ltems[i].ltemValue+#32;
end;
ltms:=Newltms; //строка значений тегов
end;
374
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
//обнуление динамических массивов
procedure TAddForm. FormClose(Sender: TObject;
var Action: TCIoseAction);
begin
//изменение длины динамического массива
SetLength(ltemszo);
//изменение длины динамического массива
SetLength(Sgmt,o);
end;
end.
3.2.2. Модуль MainUnit
Создание объекта автоматизации
1. В меню File выберем пункт меню New и в нем пункт Other
(рис. 3.10).
J Delphi 7 - NDgrServer
375
РАЗРАБОТКА SCADA-СИСТЕМ
2. В появившемся окне Newltems выбираем вкладку ActiveX
и пункт Automation Object (рис. 3.11).
J New Items
Dialogs | Projects | Data Modules | IntraWeb ] WebServices
Business | WebSnap ] Web Documents | Corba
New ActiveX | Multitier | NDgrServer | Forms
COM Object COM + Event C0M+ Property Page Transactional
Object Subscripti... Object
Type Library
C Copy C Inherit C Use
Cancel I Help
Рис. 3.11. Окно Newltems
3. В появившемся окне Automation Object Wizard в поле
CoClass Name впишем NDgrSrvr. В поле Instancing
выбираем Multiple Instance. В поле Threading Model
выбираем Free (рис. 3.12).
Automation Object Wizard
X|
CoClass Name:
|NDgrSrvr
Instancing:
| Multiple Instance
Threading Model:
Free
Options
Г Generate Event support code
Cancel | Help
Рис. 3.12. Окно Automation Object Wizard
376
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
4. После нажатия кнопки ОК появляется окно Projectl.tlb
и добавляется новый модуль Unitl. Модуль сохраняем
под именем MainUnit, а проект под именем NDgrServer
(рис. 3.13).
i^NDgrServer.tlb
Э NDgrServet
NDgiSrvr
Modified [
Рис. 3.13. Создание проекта NDgrServer
Создание свойств и методов
Добавим свойства и методы в интерфейс INDgrSrvr.
1. Нажмем (рис. 3.14) на кнопку New Property верхнего
меню. При этом в интерфейс INDgrSrvr добавятся два
новых свойства Propertyl. Одно из них (рис. 3.15) будет с
атрибутом Property Get (чтение), а другое — с атрибутом
Property Put (запись).
377
РАЗРАБОТКА SCADA-СИСТЕМ
NDgrServer.tlb
JBlZJ
Я I IW
3 Л). NDgrServer
p OKQSSOSI
NDgrSrvr
Modified
. New Property n ,
| Text |
Name: |lNDgrSrvr
GU1D: |{760B6A16-9245-487B-982C-D8F0ED265EA9}
Version: [tO
Parent Interface: (IDispatch 3
Help _________________________________________________
Help String: (Dispatch interface for NDgrSrvr Object
Help Context:
Help String Context:
Рис. 3.14. Добавление новых свойств Propertyi в интерфейс INDgrSrvr
^NDgrServer.tlb
^□,xi
- NDgrServer
□ P INDgrSrvr
«Л Propertyi
£ NDgrSrw
Modified
Рис. 3.15. Свойства Propertyi и его атрибуты
378
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Для получения аналогичного результата можно нажать на
список (кнопка со стрелкой справа) (рис. 3.16). При этом можно
выбрать атрибут свойства: Read | Write, Read Only, Write Only,
Read | Write | Write By Ref.
Переименуем свойство Property 1 (рис. 3.17) с атрибутом
Property Put на Visible. Если добавляли новое свойство при помощи
кнопки New Property, то свойство Property 1 с атрибутом Property
Get удалим. Также в списке выберем тип свойства VARIANT_BOOL.
При помощи этого свойства ОРС-клиенты могут задать
видимость формы AddForm объекта автоматизации.
^NDgrServer.tlb
ЕЗ ^4 NDgr Server
Я0ИВИ1
NDgrSrvr
«? ________________________________________________________________
Read I Write
1 Readonly
£ Write Only ~|
| & Read | Write | Write By Ref 45.467B.982C-D8F0ED265EA9}
Version: [TO
Parent Interface: | IDispatch
“Help------------------------------------------------------
Help String (Dispatch interface for NDgrSrvr Object
Help Context:
Help String Context: (”
Modified
Рис. 3.16. Альтернативный способ выбора атрибута свойства Propertyi
379
РАЗРАБОТКА SCADA-СИСТЕМ
Рис. 3.17. Переименование свойства Propertyi в Visible и выбор его типа
Во вкладке Parameters (рис. 3.18) автоматически добавляет-
ся параметр Value, имеющий тип, который имеет тот же тип, что
и свойство Property Put. В нашем случае это VARIANTBOOL.
Далее для обновления программного кода необходимо нажать
на кнопку Refresh Implementation в верхнем меню (рис. 3.19).
[jjSjNDgrServer.tlb
В Л NDgrServer
Ё # INDgrSivi
Visible
NDgiSivr
Modified
Attributes Parameters ] Flags ] Text |
Return Type: |lSl5l*UHI
r Parameters-----
Name J Type
[Value
[Modifier
| VARIANT.BOOL |in]
Add | Delete | Move Up j Move Down j
Рис. 3.18. Вкладка Parameters
380
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
££ NDgrServer.tlb
[Modified
Рис. 3.19. Кнопка Refresh Implementation
В модуль MainUnit должны добавиться следующие строки:
- в раздел Protected объявления класса TNDgrSrvr
procedure Set_Visible(Value: WordBool); safecall;
- в раздел Implementation добавится процедура:
procedure TNDgrSrvr.Set_Visible(Value: WordBool);
В эту процедуру добавим строку:
AddForm.Visible:=Value;
В зависимости от параметра Value форма AddForm будет
видимой или скрытой, то есть ОРС-клиент командой NetServer.
Visible:=true (форма видима) или NetServer.Visible:=false (форма
скрыта) может управлять видимостью формы объекта автомати-
зации.
2. Далее с помощью кнопки New Method в верхнем меню до-
бавим новый метод (рис. 3.20).
381
РАЗРАБОТКА SCADA-СИСТЕМ
^oNDgrServer.tlb
NDfflServer
“ ^IIZEESDSI
Visible
NDgrSrvr
New Method L
..... [Flags
Name:
GUID:
| Text |
|lNDgiSrvr
|{760B6A16-9245-487B-982C-D8F0ED285EA9}
Version: fl.O
Parent Interface: | IDispatch
Help-
Help String:
Help Context
Help String Context: j
IDispatch interface for NDgrSrvr Object
Modified
Рис. 3.20. Добавление метода с помощью кнопки New Method
При этом добавится новый метод с именем Methodi (рис. 3.21),
который переименуем в SetSegmentName (рис. 3.22).
^NDgrServer.tlb
-Injxj
Е & NDgrServer
- iNDgrSrvr
Visible
NDgrSrvr
Modified
Рис. 3.21. Метод Methodi
382
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Go NDgrServer.tlb
.jnjxJ
>♦МI**4 > ’ Л I 7J I Л
i£ & NDgrServer
- # INDgrSrvr
Visible
NDgtSrvr
SetSegmentName
Modified
Рис. 3.22. Methodi, переименованный в SetSegmentName
Теперь во вкладке Parameters необходимо создать параметр
Value, который имеет тип BSTR. Для этого выбираем вкладку
Parameters (рис. 3.23).
^NDgrServer.tlb
* Ф 4 4 Ь £ I * М? ’ 3 м
Е & NDgrServer
S Р INDgrSrvr
J5 Visible
[SetSegmentName]
NDgrSrvr
Attributes Parameters | Flags ] Text |
Return Type: |HRESULT
Modified
Рис. 3.23. Вкладка Parameters метода SetSegmentName
383
РАЗРАБОТКА SCADA-СИСТЕМ
При помощи кнопки Add добавим новый параметр, который
по умолчанию имеет имя Param 1 и тип long (рис. 3.24).
Переименуем Paraml в Value и выберем тип BSTR (рис. 3.25).
Г NDgrServer.tlb
Я Ъ $4 Ф £ I 4- - й I a
- & NDgrServer
1-1 р INDgrSrvr
Visible
4 SetSegmentName
ф NDgrSrvr
Attributes Parameters ] яад$ | Text |
Return Туре: jHRESULT
Рис. 3.24. Добавление параметра Parami
Modified
Рис. 3.25. Переименование Parami в Value и выбор его типа
384
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
С помощью кнопки Refresh Implementation обновим про-
граммный код в верхнем меню. В модуле MainUnit в процедуре
procedure TNDgrSrvr.SetSegmentName const Value: WideString)
добавим процедуру AddSegment(Value) из модуля AddUnit.
Она добавляет заданный сегмент в ОРС-сервер, то есть
ОРС-клиенты командой NetServer. SetSegmentName(6UltraNet_l’)
могут добавлять сегменты в ОРС-сервер.
3. Далее (рис. 3.26) с помощью кнопки New Method добавим
в ОА новый метод и назовем его SetltemName.
Во вкладке Parameters (рис. 3.27) добавим два параметра:
Value типа BSTR и Segment типа BSTR.
С помощью кнопки Refresh Implementation обновим про-
граммный код. В процедуру procedure TNDgrSrvr.SetltemName
(const Value, Segment: WideString) добавим процедуру Additem
(Value,Segment) из модуля AddUnit.
Она добавляет заданный тег в ОРС- сервер. При этом с по-
мощью команды N etServer.SetltemN ame(‘UltraN et_l .FE.Vxod 1 ’,
’UltraNet_l’) ОРС-клиенты могут добавлять теги в ОРС-сервер.
NDgrServer.tlb
-□JX
> Ф » А Ь ф £ | * «й ’ 1 <1 < Ла
В Л NDgrServer
В INDgrSfvi
Visible
J SetSegmentName
w J?
NDgrSrvr
Modified |
Рис. 3.26. Добавление метода SetltemName
385
РАЗРАБОТКА SCADA-СИСТЕМ
^NDgrServer.tlb
- |al2<j
* «й Ч £1 < I 3 М
В Л NDgrServer
S INDgrSrvr
Visible
wr SetSegmentName
4b SetltemName
NDgrSrvr
Attributes Parameters | Flags | Text |
Return Type; |HRESULT
Modified
T
Рис. 3.27. Добавление методу SetltemName параметров Value и Segment
4. Далее (рис. 3.28) добавим новое свойство с атрибутом
Property Get и переименуем его в Error. Тип свойства
Error установим в VARIANT BOOL.
NDgrServer.tlb
JnjxJ
NDgrServer
В INDgrSrvr
Visible
4* SetSegmentName
4k SetltemName
NDgrSrvr
Modified
Рис. 3.28. Добавление свойства Error и выбор его типа
386
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Параметр Value, который имеет тип VARIANTBOOL, доба-
вится автоматически.
При помощи кнопки Refresh Implementation обновим про-
граммный код. При этом в программный код модуля MainUnit
добавится функция function TNDgrSrvr.GetError: WordBool.
В нее введем следующую строку: Result:=Error;
Переменная Error описана в модуле AddUnit и предназна-
чена для хранения признака ошибки последней операции с ОРС-
сервером. При ее значении true произошла ошибка, при значении
false — нет. Таким образом, ОРС-клиенты могут считывать признак
ошибки при помощи команды NetServer.Error.
5. Добавим (рис. 3.29) новое свойство с атрибутом Property
Get и переименуем его в Itms. Тип свойства Itms установим
в BSTR. Параметр Value, имеющий тип BSTR добавится
автоматически (рис. 3.30).
Обновим программный код с помощью кнопки Refresh
Implementation и в добавленную автоматически функции function
TNDgrSrvr.Getltms: WideString введем строку: Result:=Itms.
Переменная Itms описана в модуле AddUnit и предназна-
чена для хранения всех добавленных в ОРС-сервер значений те-
гов в виде строки значений, разделенных пробелами, например:
‘0.456 2.298 4.251 8.666 ... 2.329’.
При этом ОРС-клиенты могут получить значения тегов из этой
переменной с помощью команды NetServer.Itms.
387
РАЗРАБОТКА SCADA-СИСТЕМ
Р? NDgrServer.tlb
-=Ю12<1
Лэ 04
S & NDgrServer
S INDgrSrvr
jgS Visible
A SetSegmentName
4 SetltemName
t/i Error
IE®
NDgrSrvt
Modified
Рис. 3.29. Добавление свойства Itms и выбор его типа
^NDgrServer.tlb
- NDgrServer
о > INDgrSrvr
Visible
4и SetSegmentName
4 SetltemName
Error
4^ NDgrSrvr
Attributes Parameters | Flags | Text |
Return Type: |HRESULT
Parameters
I Name J Type | Modifier |
— BSTR" [out retval]
Value
Delete Move Up Move Down
Modified
Рис. 3.30. Автоматическое добавление параметра Value
388
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
6. Добавим (рис. 3.31) новое свойство с атрибутом Property
Get и переименуем его в Server_Enabled. Установим его
тип VARIANTBOOL.
Параметр Value типа VARIANT_BOOL добавится автомати-
чески (рис. 3.32).
[^NDgrServer.tlb
>❖4 * к Ф £ | > ' ^1 S й
- > INDgrSrvr
’jS Visible
A SetSegmentName
A SetltemName
Error
ЦгД Itms
NDgrSrvr
[Server_Enabled|
Modified
Рис. 3.31. Добавление свойства Server_Enabled и выбор его типа
^NDgrServer.tlb
> ❖ 4 4 » 4- -О г 3 | М
Я NDgrServer
F! INDgrSrvr
Visible
A SetSegmentName
A SetltemName
Error
Itms
Server_Enabled
£ NDgrSrvr
'Modified
Рис. 3.32. Автоматическое добавление параметра Value
389
РАЗРАБОТКА SCADA-СИСТЕМ
С помощью кнопки Refresh Implementation обновим про-
граммный код и в функции function TNDgrSrvr.GetServerEnabled:
WordBool добавим следующую строку: Result:=Server_Enabled.
Переменная ServerEnabled объявлена в модуле AddUnit и
предназначена для хранения признака занятости ОА каким-либо
ОРС-клиентом (true — ОА свободен, false — ОА занят). При по-
мощи команды NetServer. Server Enabled ОРС-клиент может опре-
делить состояние ОРС-сервера.
7. Добавим (рис. 3.33) новый метод и переименуем его в
SetServerName. Во вкладке Parameters (рис. 3.34) добавим
параметр Value типа BSTR.
Обновим программный код и в процедуру procedure TNDgrSrvr.
SetServerName(const Value: WideString) вставим процедуру:
AddServer(Value), которая описана в модуле AddUnit и предназначе-
на для запуска ОРС-сервера.
Таким образом, ОРС-клиент с помощью команды NetServer.
SetServerName^ Имя сервера’) может запускать ОРС-сервер.
Рис. 3.33. Добавление метода SetServerName
390
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
I NDgrServer.tlb
Ф 4k tb ' | Ф1 131
Е •& NDgrServer
S INDgrSrvr
Visible
4 SetSegmentName
4 SetltemName
Error
%j Itms
Server__Enabled
4 SetServerName
NDgrSrvr
[Modified
Attributes Parameters | Flags | Text |
Return Type: |HRESULT
Parameters
Name |Type
Value.......^BSTR
| Modifier
[in]
Add | Delete | Move Up | Move Down |
Рис. 3.34. Добавление методу SetServerName параметра Value
8. Добавим (рис. 3.35) новое свойство с атрибутом Property
Get и переименуем его в Server_Exists. Выберем его тип —
VARIANT BOOL.
NDgrServer.tlb
I Sg IЛ
В & NDgrServer
Jb INDgrSrvr
Visible
4 SetSegmentName
4 SetltemName
Error
Itms
Server_Enabled
4b SetServerName
NDgrSrvr
Modified
Рис. 3.35. Добавление свойства Server_Exists и выбор его типа
391
РАЗРАБОТКА SCADA-СИСТЕМ
Обновим программный код и в функцию function TNDgrSrvr.
Get_ServerExists: Word Bool добавим строки:
Result:=false;
if Serveronil then
Result:=true;
Функция возвращает состояние ОРС-сервера: запущен — true,
выключен — false. При этом ОРС-клиент с помощью свойства
NetServer. ServerExists может определить состояние ОРС-сервера.
Параметр Value типа VARIANTBOOL добавится автомати-
чески (рис. 3.36).
i^NDgrServer.tlb
3 , 3 IМ
JBlxl
NDgrServer
В ifb INDgrSrvr
’^5 Visible
4 SetSegmentName
SetltemName
Error
Itms
oj, Server_Enabled
J SetServerName
<>44 @303302
NDgrSrvr
Attributes Parameters | Flags | Text |
Return Type: |HRESULT
Modified
Рис. 3.36. Автоматическое добавление параметра Value
9. Добавим (рис. 3.37) новое свойство с атрибутом Property
Get и переименуем его в Segments. Выберем тип свойства
Segments — BSTR. Параметр Value типа BSTR добавится
автоматически (рис. 3.38)
392
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Рис. 3.37. Добавление свойства Segments и выбор его типа
^NDgrServer.tlb
= PL*J
- NDgrServer
Н Р INDgrSrvr
jS Visible
4 SetSegmentName
4 SetltemName
Error
Itms
ServerEnabled
4 SetServerName
6^1 Ser ver Exists
» Jjv i-'1- —
«£ NDgrSrvr
Modified
Attributes Parameters | Rags ] Тек! |
Return Type: (HRESULT
Parameters-----------------------------------------------------------------|
[Name |Type |ModHier |
BSTR x [out, retval]
Value
Add
Delete I Move Up I Move Down
Рис. 3.38. Автоматическое добавление параметра Value
393
РАЗРАБОТКА SCADA-СИСТЕМ
Обновим программный код и в функции function TNDgrSrvr.
Get Segments:WideString добавим следующую строку: Result:=
SegmentsExists.
Функция возвращает строку с именами всех добавлен-
ных сегментов, записанных через пробел, например 6UltraNet_l
UltraNet_2 ... UltraNet_8’. Таким образом, ОРС-клиент с помощью
свойства NetServer.Segments может узнать имена всех ранее добав-
ленных в ОА сегментов.
10. Добавим (рис. 3.39) новое свойство и переименуем его
в Items. Выберем его тип — BSTR.
f^NDgrServer.tlb
S A NDgrServer
- j) INDgrSrvr
SetSegmentName
SetltemName
<P) Error
Itms
Server„Enabled
SetServerName
Serve (Exists
Segments
Visible
NDgrSrvr
JpJ.xJ
Рис. 3.39. Добавление свойства Items и выбор его типа
394
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Параметр Value типа BSTR добавится автоматически (рис. 3.40).
NDgrServer.tlb
• 110 < -~а М
S & NDgrServer
Е INDgrSrvr
J SetSegmentName
4 SetltemName
fr/i Error
fr/ Itms
Server_Enabled
4 SelServerName
ServerExists
Segments
Visible
NDgrSrvr
Attributes Parameters | Flags | Text |
Return Type: |HRESL1LT
Рис. ЗАО. Автоматическое добавление параметра Value
Обновим программный код и в функции function TNDgrSrvr.
Get ltems: WideString добавим строку: Result:=ItemsExists.
Переменная ItemsExists описана в модуле AddUnit и предна-
значена для хранения имен ранее добавленных тегов. Имена тегов
записываются в одной строке через пробел, например: 6UltraNet_l.
FE.Vxod3 UltraNetl.FE.s ... UltraNet_l.FD.temp’. Таким образом,
ОРС-клиент при помощи свойства NetServer.Items может опреде-
лить имена добавленных в ОА тегов.
Программный код модуля MainUnit приведен в листинге 3.2.
Листинг 3.2
unit MainUnit;
{$WARN SYMBOL_PLATFORM OFF}
interface
uses
ComObj, ActiveX, NDgrServer_TLB, StdVcl;
type
395
РАЗРАБОТКА SCADA-СИСТЕМ
TNDgrSrvr = class(TAutoObject, INDgrSrvr)
protected
//установка видимости формы объекта автоматизации
procedure Set_Visible(Value: WordBool); safecall;
//возвращает true, если была ошибка
//и false в противном случае
function Get_Error: WordBool; safecall;
//добавляет в ОРС-сервер сегмент Value
procedure SetSegmentName(constValue: WideString); safecall;
//добавляет тег Value в сегмент Segment
procedure SetitemName(const Value, Segment: WideString);
safecall;
//запускает ОРС-сервер Value
procedure SetServerName(constValue: WideString); safecall;
//возвращает строку co значениями всех тегов
function Getjtms: WideString; safecall;
//возвращает true, если объект автоматизации свободен
//и false в противном случае
function Get_Server_Enabled: WordBool; safecall;
//возвращает true, если ОРС-серверуже запущен
function Get_ServerExists: WordBool; safecall;
//возвращает строку с именами всех добавленных сегментов
function Get_Segments: WideString; safecall;
//возвращает строку с именами всех добавленных тегов
function Getjtems: WideString; safecall;
end;
implementation
uses ComServ, AddUnit, SysUtils;
//устанавливает видимость формы объекта автоматизации
procedure TNDgrSrvr.Set_Visible(Value: WordBool);
begin
//установка видимости формы объекта автоматизации
AddForm. Visible:=Value;
end;
//возвращает признак ошибки последней операции
function TNDgrSrvr.Get_Error: WordBool;
begin
//возвращает признакошибки
Result:=Error;
end;
396
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
//добавление сегмента
procedure TNDgrSrvr.SetSegmentName(const Value: WideString);
begin
//добавление сегмента
AddSegment(Value);
end;
//добавление тега
procedure TNDgrSrvr.SetltemName(const Value,
Segment: WideString);
begin
//добавление тега
AddltemtValue, Segment);
end;
// запуск ОРС-сервера
procedure TNDgrSrvr.SetServerName(const Value: WideString);
begin
//запуск ОРС-сервера
AddServer(Value);
end;
//значения тегов
function TNDgrSrvr.GetJtms: WideString;
begin
// возвращает значения тегов
Result:=ltms;
end;
// возвращает признак занятости объекта автоматизации
function TNDgrSrvr.Get_Server_Enabled: WordBool;
begin
// возвращает признак занятости объекта автоматизации
Result:=Server_Enabled;
end;
//возвращает статус ОРС-сервера
function TNDgrSrvr.Get_ServerExists: WordBool;
begin
//установка значения по умолчанию (ОРС-сервер не запущен)
Result:=false;
// если ОРС-сервер уже запущен
if Serveronil then
Result:=true;
end;
397
РАЗРАБОТКА SCADA-СИСТЕМ
//возвращает строку имен сегментов
function TNDgrSrvr.Get_Segments: WideString;
begin
//возвращает строку с именами всех добавленных сегментов
Result:=Segments Exists;
end;
//возвращает строку с именами всех добавленных тегов
function TNDgrSrvr.GetJtems: WideString;
begin
//возвращает строку с именами всех добавленных тегов
Result:=ltemsExists;
end;
initialization
TAutoObjectFactory.Create(ComServer, TNDgrSrvr, Class_NDgrSrvr,
ci Multi In stance, tmFree);
end.
3.2.3. Практическая работа с объектом автоматизации
1. Запустим утилиту scktsrvr.exe, входящую в состав Borland
Delphi (C:\Program Files\Borland\Delphi7\Bin) (рис. 3.41).
Файл Правка Вид Избранное Сервис Справка
Назад ’ | у”'1 Поиск ’ Папки | jA Х«9
Адрес: | / C:\Program Files\Borland^Delphi7\Bin
J±l)dclwbm70.bpl
]ddwbm70.map
3jddwebsnap70.bpl
]ddwebsnap70.map
2^DELPHI32.DCI
^delphi32.dmt
^defphi32.dro
> delphi32.exe
^defphi.dct
j*l]Delphi.upg
2±l]delphiclxide7C.bpl
2±l]delphjde7O.bpl
^defphient70.bpl
'jdelphimm.dll
^detphjpro70.bpl
^jdefphivdide70.bpl
j^denmarkdem
23]designdgm7O.bpl
designide70.bpl
2±Jdfm7O.bpl
ldfwedit.DLL
Bdirect7O.bpl
etm70.exe
*| exptdemo.dB
2f] frameset.dtd
£[f rance, dem
^jgermany.dem
Zl grep.exe
^HTML2.dtd
HTMLZ-strict.dtd
3$HTML3.2.dtd
htmlide70.bpl
^HTMLlatl.ent
'^HTMLspecial.ent
^HTMLsymboI.ert
*j httpsrvr.dD
~o~lidl2oas.bat
3§Idl2pas.jar
^Idl2PasWizardPkg.bpl
I Idl2PasWizardPkg.map
imagedit.exe
Д imged32.dll
3ljindy70.bpl
_Jindy70.map
<| isapiter.dll
Sjitaly.dem
3fitecore70.bpl
'^iteide70.bpl
'Sfjapan.dem
,^|korea.dem
,<| lnkdfm70.dll
jdjloose.dtd
lmake.exe
Msglnfo70.bpl
_vmsginfo70.ini
_jMsgInfo70.map
lmtsinst.exe
J-jinetherld.dem
norway.dem
Ooh.exe
_4dh.ini
OrbPas45.dB
Й^рсе.ехе
phone.txt
j^proide70.bpl
Йгс70.Ьр1
jrc70.map
<| rBnk32.de
* J rw32core.dll
I smdient.dB
J^spain.dem
iSQLB.DLL
F0jsqImon.exe
ill statelist.txt
3istdvd4O.tlb
^10 Переход
_^)stride70.b
aS] Sweden, dt
^Jtaiwan.dei
ZjTDUMP.EX
^]tlib70.bpl
rlttbimp .exc
^tlibimp.syn
2]tregsvr.ex
uk. dem
j^|u$.dem
^vddesigne
2f]vdhie70.b
^]vclide70.b
Jjvdtest3.dl
’gwebappdb
^WebLib.tlt
J]wmll2.dtd
& WS32.EXE
^JWSDLlmp.
^xhtmll-fra
xhtml 1-str
£l]xhtmll-tra
4±l]xhtml-lati
j^]xhtml-spet
j^lxhtml-sym
,Uxmlide.de
Описание: Borland Socket Server Произ: 662 КБ
Мой компьютер
Рис. 3.41. Утилита scktsrvr.exe в папке C:\Program Files\Borland\Delphi7\Bin
398
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
2. Щелчком правой кнопкой мыши по иконке Borland Socket
Server (в трее) вызываем контекстное меню и щелкаем
по пункту меню Properties (рис. 3.42).
Close
Properties
Рис. 3.42. Меню Properties в контекстном меню Borland Socket Server
Появляется окно Borland Socket Server (рис. 3.43).
Borland Socket Server
XI
Ports Connections
Port j [ Properties]] Users |
211
Port
Listen on Port: 211 -$j
Many values of Port are associated by convention with a
particular service such as ftp or http. Port is the ID of the
connection on which the server listens for client requests.
Thread Caching------------ — — —
Thread Cache Size: 110 -jj
Thread Cache Size is the maximum number of threads that can
be reused for new client connections.
T imeout--------------——
Inactive Timeout: |o -j
Inactive Timeout specifes the number of minutes a client can
be inactive before being disconnected. (0 indicates infinite)
Intercept GUID
GUID: |
Intercept GUID is the GUID for a data interceptor COM object.
See help for the TSocketConnection for details.
Рис. 3.43. Окно Borland Socket Server
399
РАЗРАБОТКА SCADA-СИСТЕМ
3. Выбираем вкладку Connections (рис. 3.44).
Borland Socket Server
2d
Ports Connections
Port Show Host Name
0ЯИ v* Registered Objects Only
v Allow XML Packets
'•rt: И1
Disconnect —
------------- -............ .u are associated by convention with a
particular service such as ftp or http. Port is the ID of the
connection on which the server listens for client requests.
Thread Caching
Thread Cache Size: 10 vj
Thread Cache Size is the maximum number of threads that can
be reused for new client connections.
“Timeout
Inactive Timeout [o Tj
Inactive Timeout specifes the number of minutes a client can
be inactive before being disconnected. (0 indicates infinite]
Intercept GUID
GUID: |
Intercept GUID is the GUID for a data interceptor COM object.
See help for the TSocketConnection for details.
Apply
Рис. 3.44. Вкладка Connections окна Borland Socket Server
400
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
4. Убираем «галочку» с пункта меню Registered Objects Only
(рис. 3.45).
9* Borland Socket Server
Ports Connections
Port Show Host Name
Registered Objects Only
v Allow XML Packets ____________,
—------------nt: [211 Д
Disconnect t ~1
------- .. .j . .......... are associated by convention with a
particular sei vice such as ftp or http. Port is the ID of the
connection on which the server listens for client requests.
Thread Caching
Thread Cache Size: [lU
Thread Cache Size is the maximum number of threads that can
be reused for new client connections.
Timeout---------------—------------------------------------
Inactive Timeout: [5 Tj
Inactive Timeout specifes the number of minutes a client can
be inactive before being disconnected. (0 indicates infinite]
Intercept GUID
GUID: |
Intercept GUID is the GUID for a data interceptor COM object.
See help for the TSocketConnection for details.
Apply
Рис. 3.45. Пункт меню Registered Objects Only граница слева
5. Перезапускаем утилиту.
6. Запускаем и закрываем наш объект автоматизации, то есть
приложение NDgrServer.exe. Это делается для его регистра-
ции в реестре Windows (рис. 3.46).
7. Действия 1-6 выполняются один раз при настройке утили-
ты scktsrvr.exe. В дальнейшем удобно добавить эту утили-
ту в автозапуск Windows. Для автоматической регистрации
объекта автоматизации в реестре Windows при перемеще-
нии объекта автоматизации в другое место необходимо вы-
полнить действие 6 снова.
401
РАЗРАБОТКА SCADA-СИСТЕМ
|Й1 Сервер для N-каналов -|n|x|
Файл Правка Вид Избранное Сервис Справка
Назад * > J Поиск Папки
Адрес: |_j О:\Контроллер\Сервер для N-каналов ifl Переход
j±j| AddUnit. ~ddp j±j] NDgrServer .^dpr NDgrServer_TLB.pas AddUnit. ~dfm У] NDgrServer. ~tlb jS|OPCDA.dcu jd) AddUnit. ~pas NDgrServer. cfg sf/OPCDA.pas jdjAddUnit.dcu NDgrServer. dof ^OPCtypes.dcu ^AddUnit.ddp jb NDgrServer. dpr OPCtypes.pas
_c>AddUnit.dfm ЗИ! SOPCUtils.dcu
^AddUnit.pas £j| NDgrServer. res OPCutils.pas jgj] MainUnit. ^pas NDgrServer. tlb scktsrvr.exe MainUnit. dcu j±I] NDgrServer_TLB.~pas MainUnit. pas S±f, NDgrServer_TLB.dcu
Дата создания: 25.10.200( 402 КБ | 3) Мой компьютер
Рис. 3.46. Регистрация приложения NDgrServer.exe в реестре Windows
3.2.4. Модуль NDgrServer_TLB
Программный код модуля NDgrServerTLB приведен в ли-
стинге 3.3.
Листинг 3.3
// PASTLWTR : 1.2
II ккккккккккккккккккккккккккккккккккккккккккккккккккк Ц
//Type Lib: 0:\Контроллер\Сервер для Ы-каналов\Ы0дг5егуег11Ь (1)
// LIB ID: {23170B6D-1F7B-4ECF-B89D-EC582A6C5F98}
// LCID: о
// Helpfile:
// HelpString: NDgrServer Library
// DepndLst:
// (1) V2.0 stdole, (C:\WINDOWS\system32\stdole2.tlb)
II к к к к к к к к к к к к к к к к к к к к к к к к к к к к к к к к к к к к к к к к к к к к к к к к к к к Ц
{$TYPEDADDRESS OFF} //Unit must be compiled without type-checked
pointers.
{$WARN SYMBOL-PLATFORM OFF}
{$WRITEABLECONST ON}
{$VARPROPSETTER ON}
402
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
interface
uses Windows, ActiveX, Classes, Graphics, StdVCL, Variants;
II •к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'кЦ
//GUIDS declared in theTypeLibrary. Following prefixes are used:
// Typelibraries : LIBID_xxxx
// CoClasses : CLASS. -XXXX
// DISPInterfaces : DIID_xxxx
// Non-DISP interfaces: IID_xxxx
II •к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'кЦ
const
//TypeLibrary Major and minor versions
NDgrServerMajorVersion = i;
NDgrServerMinorVersion = o;
LI Bl D_N DgrServer:TG UID=I23170B6D-1F7B-4ECF-B89D- EC582A6C5F98}1;
IIDJNDgrSrvr:TGUID = l{76oB6Ai6-9245-487B-982C-D8FoED265EA9}1;
CLASS_N DgrSrvr: TG UID = '{D48FOC4F-C31A-4CD7-9653-B965826B39OQ1;
type
II 'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'кЦ
II Forward declaration of types defined in TypeLibrary
II 'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'кЦ
INDgrSrvr = interface;
INDgrSrvrDisp = dispinterface;
II 'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'кЦ
II Declaration of CoClasses defined in Type Library
// (NOTE: Here we map each CoClass to its Default Interface)
II •к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'кЦ
NDgrSrvr = INDgrSrvr;
II 'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'кЦ
II Interface: INDgrSrvr
// Flags: (6464) Dual OleAutomation Replaceable Dispatchable
//GUID: {760B6A16-9245-487B-982C-D8F0ED265EA9}
II 'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'кЦ
INDgrSrvr = interface(IDispatch)
['{76oB6Ai6-9245-487B-982C-D8FoED265EA9}']
procedure Set_Visible(Value: WordBool); safecall;
procedure SetSegmentName(constValue: WideString); safecall;
procedure SetltemName(const Value: WideString; const Segment:
403
РАЗРАБОТКА SCADA-СИСТЕМ
Wid-eString); safecall;
function Get_Error: WordBool; safecall;
function Getjtms: WideString; safecall;
function Get_Server_Enabled: WordBool; safecall;
procedure SetServerName(constValue: WideString); safecall;
function Get_ServerExists: WordBool; safecall;
function Get_Segments: WideString; safecall;
function Getjtems: WideString; safecall;
property Visible: WordBool write Set_Visible;
property Error: WordBool read Get_Error;
property Itms: WideString read Getjtms;
property Server_Enabled: WordBool read Get_Server_Enabled;
property ServerExists: WordBool read Get_ServerExists;
property Segments: WideString read Get_Segments;
property Items: WideString read Getjtems;
end;
II 'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'кЦ
// Displntf: INDgrSrvrDisp
// Flags: (6464) Dual OleAutomation Replaceable Dispatchable
//GUID: {760B6A16-9245-487B-982C-D8F0ED265EA9}
II •к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'кЦ
INDgrSrvrDisp = dispinterface
IJ760B6A16-9245-487B-982C-D8F0ED265EA9}1]
property Visible: WordBool writeonly dispid 201;
procedure SetSegmentName(constValue: WideString); dispid 202;
procedure SetltemName(const Value: WideString; const Segment:
Wid-eString); dispid 203;
property Error: WordBool readonly dispid 204;
property Itms: WideString readonly dispid 205;
property Server_Enabled: WordBool readonly dispid 207;
procedure SetServerName(constValue: WideString); dispid 206;
property ServerExists: WordBool readonly dispid 210;
property Segments: WideString readonly dispid 208;
property Items: WideString readonly dispid 209;
end;
II •к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'кЦ
//The Class CoNDgrSrvr provides a Create and Create Re mote method to
// create instances of the default interface INDgrSrvr exposed by
// the CoClass NDgrSrvr. The functions are intended to be used by
// clients wishing to automate the CoClass objects exposed by the
// server of th is typelibrary.
404
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
II 'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'к'кЦ
CoNDgrSrvr = class
class function Create: INDgrSrvr;
class function CreateRemote(const MachineName: string): INDgrSrvr;
end;
implementation
uses ComObj;
class function CoNDgrSrvr.Create: INDgrSrvr;
begin
Result := CreateComObject(CLASS_NDgrSrvr) as INDgrSrvr;
end;
class function CoNDgrSrvr.CreateRemote(const MachineName: string):
INDgrSrvr;
begin
Result := CreateRemoteComObject(MachineNamez CLASS_NDgrSrvr)
as INDgrSrvr;
end;
end.
3.3. Назначение и организация ОРС-клиента
3.3.1. Функции, выполняемые ОРС-клиентом
ОРС-клиенты представляют собой приложения (програм-
мы), расположенные на удаленных компьютерах локальной сети
Ethernet. Они предназначены для чтения информации с контрол-
леров, подключенных к промышленной сети PLCNet. Чтение
информации осуществляется с использованием ОРС-сервера,
расположенного на специально выделенном компьютере сети
Ethernet — мастере (хосте).
Кроме этого ОРС-клиент может обрабатывать полученную
из контроллеров информацию и выводить ее на экран удаленного
компьютера в нужной форме. К локальной сети Ethernet может быть
подключено произвольное число удаленных компьютеров. Резуль-
таты работы распределенной системы управления технологическим
оборудованием могут передаваться на любое число этих компьюте-
ров. Важно, чтобы на каждом из них работал ОРС-клиент.
405
РАЗРАБОТКА SCADA-СИСТЕМ
ОРС-клиенты, расположенные на компьютерах диспетчерско-
го (операторского) уровня РСУ, могут быть совершенно разными
приложениями.
3.3.2. Хранение данных в ОРС-клиенте
Организация хранения и обработки данных в любом ОРС-
клиенте естественным образом вытекает из организации локальной
сети PLCNet, которую можно описать структурой: сегменты
узлы —> теги.
В этой структуре:
- сегмент — фрагмент сети, объединяющий группу контрол-
леров и подключений к одному из COM-портов мастера;
- узел сети — контроллер;
- тег — значение какой-либо переменной, которая отражает со-
стояние какого-либо датчика (входная переменная), либо ис-
пользуется в качестве управляющего воздействия для опреде-
ленного исполнительного механизма (выходная переменная).
Необходимо отметить, что тегом может быть и любая проме-
жуточная переменная, использующаяся в УПК. Важным является
то, что бы контроллер регулярно отправлял значения нужных пе-
ременных в локальную сеть PLCNet. Такие переменные называют-
ся сетевыми. Таким образом, каждой сетевой переменной соответ-
ствует понятие тега.
Для системы программирования UltraLogik любую переменную
УПК (входную, выходную, промежуточную) можно легко сделать се-
тевой, если в проекте нужной переменной присвоить статус «сетевая».
В структуре приложения ОРС-клиента (табл. 3.1) можно выде-
лить три части:
- архив, который предназначен для хранения значений тегов,
полученных по сети;
- исполнительная часть, которая представляет собой набор
компонентов ОРС-клиента, его процедуры и функции, пред-
назначенные для организации обмена между ОРС-клиентом
и ОРС-сервером мастера;
- графическая часть, которая представляет собой набор ком-
понентов, процедур и функций, предназначенных для выво-
да на экран компьютера:
406
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
• значений тегов;
• графических образов, отображающих в той или иной
форме значений тегов;
• графических образов, отображающих состояние груп-
пы тегов;
• графических образов, отображающих состояние всего
управляемого технологического процесса или его со-
ставляющих.
Таблица 3.1
АРХИВ ИСПОЛНИТЕЛЬНАЯ ЧАСТЬ ГРАФИЧЕСКАЯ ЧАСТЬ
Хранение полученных данных Segments Nodes Items (сегменты узлы теги) Компоненты, процедуры и функции, осуществляющие обмен данными между ОРС-клинтом и ОРС-сервером Компоненты, процедуры и функции, осуществляющие вывод на экран значений тегов, диаграмм или графиков по запросу оператора
Архив
Архив имеет иерархическую структуру (рис. 3.47). Она при-
ведена на рис. 3.48. Поскольку приложение, реализующее ОРС-
клиент, является универсальным и может работать с произвольным
количеством сегментов, узлов и тегов, то для хранения таким обра-
зом структурированных данных целесообразно использовать дина-
мические массивы. Всего используются три динамических массива:
Segments, Nodes и Items. Структура взаимодействия этих массивов
представлена на рис. 3.49.
Рис. ЗА7. Иерархия элементов архива
407
Рис. ЗА8. Структура архива
Рис. ЗА9. Структура взаимодействия массивов Segments, Nodes и Items
РАЗРАБОТКА SCADA-СИСТЕМ
Массив Segments элементов типа TSegment предназначен для
хранения всей информации о промышленной сети.
Тип TSegment предназначен для сетевого описания сегментов
сети и содержит следующие поля:
- SegmentName — имя сегмента;
- Segment — интерфейс, осуществляющий добавление и уда-
ление тегов в сегмент;
- SegmentHandle — уникальный числовой идентификатор
сегмента;
- NodesCount — количество узлов в данном сегменте;
- Nodes — динамический массив, в котором хранится вся ин-
формация об узлах, входящих в сегмент;
- TreeSegment — признак того, что сегмент является элемен-
том иерархической структуры, которую можно представить
в виде дерева в окне компонента TreeViewl.
Массив Nodes элементов типа TNode предназначен для хране-
ния всей информации об узлах, входящих в сегменты сети.
Тип TNode предназначен для сетевого описания узлов (кон-
троллеров) и содержит следующие поля:
- NodeName — имя узла.
- ItemsCount — количество тегов, подключенных к данному
узлу;
- Items — динамический массив для хранения информации
о тегах узла;
- TreeNode — признак того, что узел является элементом ие-
рархической структуры, которую можно представить в виде
дерева в окне компонента TreeViewl;
Массив Items элементов типа TItem предназначен для
хранения всей информации о тегах, входящих в узлы сегмен-
тов.
Тип TItem предназначен для описания тегов и содержит следу-
ющие поля:
- ItemName — имя тега;
- ItemHandle — уникальный числовой идентификатор тега;
- ItemType — тип тега;
- ItemValue — значение тега;
- ItemQuality — качество передачи тега по сети;
410
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
- Treeitem — указывает то, что тег включен в иерархическую
структуру, которую можно представить в виде дерева в окне
компонента TreeViewl;
- Number — порядковый номер тега в списке, получаемого от
объекта автоматизации.
Компоненты, используемые в приложении — ОРС-клиенте
Форма приложения содержит следующие компоненты:
- TreeViewl — дерево просмотра, которое используется для
отображения иерархии данных в виде дерева, в котором
пользователь может выбрать (выделить) нужный ему эле-
мент: сегмент, узел и тег;
- Timeri — таймер служит для задания временных интерва-
лов, используемых при работе приложения;
- ItemValue: TLabeledEdit — поле для вывода значения тега
(переменной), выделенного в окне компонента TreeViewl;
- ItemQuality: TLabeledEdit — поле для вывода качества прие-
ма тега, выделенного в окне компонента TreeViewl;
- GroupBoxl — контейнер, используемый для визуального
объединения компонентов ItemValue и ItemQuality;
- OPCServer: TLabeledEdit — поле для ввода имени ОРС-
сервера;
- NServer: TLabeledEdit — поле для ввода имени объекта ав-
томатизации (Automation Object);
- GroupBox2 — контейнер, используемый для визуального
объединения компонентов OPCServer и NServer;
- HostName: TLabeledEdit — поле ввода вывода для ввода
имени мастера;
- HostIP: TLabeledEdit — поле для ввода IP-адреса мастера;
- GroupBox3 — контейнер, используемый для визуального
объединения компонентов HostName и HostIP;
- SaveDialogl — используется для сохранения иерархическо-
го дерева (сегмент, узел, тег), расположенного в окне компо-
нента Tree View 1;
- OpenDialog 1 — используется для открытия в окне Tree View 1
ранее сохраненного в файле иерархического дерева (сег-
мент, узел, тег);
411
РАЗРАБОТКА SCADA-СИСТЕМ
- SocketConnection предназначен для организации переда-
чи данных на другие компьютеры (рабочие станции) сети
Ethernet.
3.3.3. Обработка данных в ОРС-клиенте
Процедуры, реализующие реакцию приложения
на различные события
FormCreate
Выполняется в момент создания формы MainForm приложе-
ния на экране и осуществляет следующие действия: динамически
создает пункты основного меню, подменю и назначает процедуры
для подменю. Также осуществляется чтение имен ОРС-сервера
и объекта автоматизации, имени и IP-адреса мастера из файла sys.sy.
Алгоритм процедуры приведен на рис. 3.50.
Рис. 3.50. Алгоритм процедуры FormCreate
412
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
LocalClick
Выполняются действия, связанные с выбором мышью пункта
меню «ОРС-сервер». При этом реализуются следующие действия:
- запускается ОРС-сервер;
- запрещается работа с пунктом меню «Пуск», окнами ввода
вывода HostName. HostIP, NServer, OPCServer;
- разрешается работа с пунктами меню «Стоп», «Добавить
сегмент» UltraNet, «Удалить сегмент» UltraNet, «Доба-
вить узел», «Удалить узел», «Добавить тег», «Удалить
тег»;
- обнуляется счетчик элементов SegmentsCount массива
Segments.
Алгоритм процедуры приведен на рис. 3.51.
Процедура LocalClick
Лист 1
Всего 1
Рис. 3.51. Алгоритм процедуры LocalClick
413
РАЗРАБОТКА SCADA-СИСТЕМ
RemoteClick
Осуществляет действия, связанные с выбором пункта меню
Automation Object. Осуществляется запуск объекта автоматизации.
Если объект автоматизации NetServer не был запущен ранее,
то выполняются следующие действия:
- Свойству Host компонента SocketConnection 1 присваивает-
ся значение свойства Text компонента HostName. Физиче-
ски в Host будет храниться сетевое имя мастера, например,
СОМР12.
- Свойству SocketConnectionl.Adress компонента
SocketConnection 1 присваивается значение свойства Text
компонента HostIP. Физически в Adress будет храниться се-
тевой адрес мастера, например 192.168.0.12.
- Свойству SocketConnection 1 .ServerName, присваивается
значение свойства Text компонента NServer, например,
NDgrServer.NDgrServer. Здесь компонент NDgrServer есть
название проекта объекта автоматизации (объект автомати-
зации также представляет собой приложение, выполненное
в Delphi, откомпилированное и расположенное на мастере).
Компонент NDgrSrvr представляет собой имя интерфейса,
описанный в приложении NDgrServer — объект автомати-
зации.
- Выполняется соединение ОРС-клиента с утилитой
scktsrvr.exe.
- Запускается объект автоматизации: SocketConnection 1.
Connected:=true.
- С экрана убирается форма только что запущенного объекта
автоматизации: NetServer. Visible:=false.
- Устанавливается в true глобальная переменная nt, указы-
вающая на признак расположения клиента на другом ком-
пьютере сети Ethernet.
- Разрешается работа с пунктами меню «Стоп», «Доба-
вить сегмент UltraNet», «Добавить узел», «Добавить
тег».
- Запрещается работа с пунктами меню «Пуск», «Удалить
сегмент UltraNet», «Удалить узел», «Удалить тег» и ком-
понентами NServer, OPCServer, HostName, HostIP.
414
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
- Переменной SegmentsCount (число сегментов сети) присва-
ивается начальное значение 0.
- Переменной ff присваивается значение false.
- Далее проверяется признак того, был ли ранее запущен
ОРС-сервер другим ОРС-клиентом, расположенным на дру-
гом компьютере сети. Если он не был запущен ОРС- клиен-
том с другого компьютера (NetServer. ServerExists=false), то
начинается цикл проверки значения переменной ff. В этом
цикле проверяется значение переменной ServerEnabled,
описанной в объекте автоматизации NetServer. Если она
имеет значение true, то объект автоматизации NetServer в
настоящий момент времени не работает ни с одним из кли-
ентов сети Ethernet. Объект автоматизации может работать
только с одним клиентом, остальные ждут своей очереди.
Таким образом, несколько клиентов не смогут совершить
одинаковых действий, например, несколько раз запустить
ОРС-сервер или добавить одинаковый тег. Следователь-
но, ОРС-клиент может работать с объектом автоматизации
(Server Enabled = true) и может запустить ОРС-сервер
с помощью метода SetServerName (OPCServer.Text). Если
при этом возникает ошибка, то выводится сообщение «Не
могу запустить сервер!!!». При этом объект автоматизации
отключается (NetServer:=O). Затем происходит отсоединение
ОРС-клиента от объекта автоматизации—SocketConnection 1.
Conneted := false. Далее запрещаются пункты меню Сегмент
Ultranet, Узел, Тег и разрешается работа с компонентами
HostName. HostIP, NServer, OPCServer.
Алгоритм процедуры приведен на рис. 3.52.
415
РАЗРАБОТКА SCADA-СИСТЕМ
Процедура Remote Click
Лист 1
Рис. 3.52. Алгоритм процедуры RemoteClick (начало)
416
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Процедура Remote Click
Лист 2
Рис. 3.52. Алгоритм процедуры RemoteClick (окончание)
417
РАЗРАБОТКА SCADA-СИСТЕМ
DisconnectClick
Осуществляется разрыв соединения между мастером и ОРС-
сервером или мастером и другими рабочими станциями сети Ethernet.
Запускается при щелчке мыши на пункте меню Disconnect
(«Стоп») меню «Файл».
При этом выполняются следующие действия:
- отключается ОРС-сервер (Server:=nil);
- уничтожается динамический массив Segments;
- ОРС-клиент отключается от объекта автоматизации;
- запрещается работа со всеми пунктами всех меню, кроме
пункта Connect;
- разрешается работа с компонентами HostName, HostIP,
NServer, OPCServer.
Алгоритм процедуры приведен на рис. 3.53.
.Лист 1
Всего 1
Процедура DiscoimeetCliek
Рис. 3.53. Алгоритм процедуры DisconnectClick
AddSegmentClick
Реализуется добавление узла (имя сегмента) в окно компо-
нента TreeViewl и добавление сегмента в ОРС-сервер. Процедура
AddSegmentClick реализована так, что учитывает работу приложе-
ния как без объекта автоматизации (ОРС-клиент расположен на ма-
стере), так и с объектом автоматизации (ОРС-клиенты расположены
на других компьютерах сети Ethernet).
418
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Эта процедура запускается щелчком мыши на пункте меню
«Добавить Сегмент Ultranet». При этом на экран поверх основ-
ной формы выводится диалоговое окно InputBox с именем «Добав-
ление сегмента Ultranet». Далее проверяется переменная nt, зна-
чение true которой отражает тот факт, что ОРС-клиент находится
на другом компьютере сети Ethernet.
Если nt=false, то ОРС-клиент находится на мастере, и нет необ-
ходимости подключаться к объекту автоматизации NetServer.
При этом выполняются следующие действия:
- содержание переменной SegmentsCount, характеризующей
число элементов в динамическом массиве Segments, увели-
чивается на 1;
- с помощью процедуры SetLeugth устанавливается длина ди-
намического массива Segments под новый сегмент;
- устанавливается в состояние nil поле Segment нового сег-
мента в массиве Segments;
- процедурой ServerAddGroup в переменной Server добавля-
ется новый сегмент (группа), которой присваивается свой
уникальный номер SegmentHadle;
- в переменной SegmentName запоминается имя сегмента;
- в дерево Tree View 1 добавляется узел с именем SegmentName,
причем этот узел не имеет родителей;
- обнуляется размер динамического массива Nodes, содержа-
щего информацию об узлах данного сегмента.
Если переменная nt=true, то это означает, что ОРС-клиент на-
ходится на удаленном компьютере и при работе с ОРС-сервером
необходимо использовать объект автоматизации. При этом выпол-
няются следующие действия:
- увеличивается на единицу значение переменной
SegmentsCount, отражающей размер динамического масси-
ва Segments;
- устанавливается новое значение размера динамического
массива Segments;
- устанавливается исходное значение переменной ff, отража-
ющей занятость объекта автоматизации;
- организуется цикл ожидания освобождения объекта авто-
матизации; как только он освободился от работы с другим
419
РАЗРАБОТКА SCADA-СИСТЕМ
ОРС-клиентом, переменная NetServer.ServerEnabled, опи-
санная в объекте автоматизации, становится равной true; при
этом в строковую переменную s из переменной NetServer.
Segments записывается список существующих сегмен-
тов сети UltraNet, разделенных пробелами, например:
UltraNetl_UltraNet2_...;
- в начало списка добавляется пробел;
- начинается заполнение элементов динамического массива
ms строкового типа, причем каждый элемент будет содер-
жать имя соответствующего сегмента сети UltraNet;
- определяется факт совпадения имени введенного сегмента
(переменная seg) и имени сегмента из динамического мас-
сива ms, сформированного на основании данных, принятых
в переменную s из объекта автоматизации;
- если добавляемый сегмент еще не добавлен (fff=false),
то объекту автоматизации пересылается имя сегмента, кото-
рый и добавляет его в ОРС-сервер;
- имя добавляемого сегмента берется из переменной seg.
В дерево Tree View 1 добавляется узел с этим именем и раз-
мер NodesCount динамического массива Nodes устанавли-
вается в ноль.
Алгоритм процедуры приведен на рис. 3.54.
420
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Рис. 3.54. Алгоритм процедуры AddSegmentClick (начало)
421
РАЗРАБОТКА SCADA-СИСТЕМ
Процедура AddSegmeiUCIick
Лист 2
Рис. 3.54. Алгоритм процедуры AddSegmentClick (продолжение)
422
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Процедура AddSegmentClick
Лист 3
1. ff принимает значение true
2. Считывание списка существующих сегментов из объекта
автоматизации
1. Добавление пробела в конец полученного списка
2. Задание начального значения счетчика]
Задание начального значение счетчика i
Да
Рис. 3.54. Алгоритм процедуры AddSegmentClick (продолжение)
423
РАЗРАБОТКА SCADA-СИСТЕМ
Процедура AddSegmentClick
Лист 4
Рис. 3.54. Алгоритм процедуры AddSegmentClick (продолжение)
424
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Лист 5
Процедура AddSegmentCJick
Рис. 3.54. Алгоритм процедуры AddSegmentClick (продолжение)
425
РАЗРАБОТКА SCADA-СИСТЕМ
426
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Процедура AddSegmentClick
Лист?
1. Заполнение полей последнего элемента массива Segments
(имя сегмента и число узлов в массиве Nodes)
2. Добавление узла с именем сегмента в компонент TreeViewl
1
I
Конец
Рис. 3.54. Алгоритм процедуры AddSegmentClick (окончание)
AddNodeClick
Реализуется добавление узла (имя узла) в окно компонента
TreeViewl.
Эта процедура вызывается при щелчке мышью на пункте меню
«Добавить узел» пункта «Узел» главного меню. При реализации
этой процедуры выполняются следующие действия:
- запускается диалог InputBox с именем «Добавление узла»,
в который пользователь должен ввести имя узла, например,
Ultranetl.FE;
- если имя было введено, то с помощью процедуры GetNames
в переменные Segment, Node, ItemID записываются элемен-
ты введенного имени; например, в переменную Segment
запишется строка Ultranet l, а в переменную Node — FE;
переменная ItemID в данном случае не используется.
- с помощью функции GetSegmentlndex(Segment) в перемен-
ную i записывается целое число, равное порядковому номе-
ру этого сегмента в массиве Segments.
- с помощью функции GetNodeIndex(Segment, Node) в пере-
менную j записывается целое число, равное порядковому
номеру узла в массиве Nodes.
427
РАЗРАБОТКА SCADA-СИСТЕМ
- далее проверяется факт наличия сегмента с заданным име-
нем (i о -1) и отсутствие узла с таким именем в качестве
Nodes (j=-l); если узел в данном сегменте отсутствует, то
узел необходимо добавлять в дерево компонента TreeViewl;
при этом выполняются следующие действия:
• увеличивается на единицу значение переменой
NodesCount, являющейся счетчиком элементов в масси-
ве Nodes, относящегося к элементам массива Segments;
• увеличивается на единицу размер динамического мас-
сива Nodes;
• полю NodeName последнего элемента массива Nodes
присваивается значение переменной Node;
• счетчик количества тегов ItemsCount обнуляется, по-
скольку в данном узле нет ни одного тега;
• в дерево TreeViewl добавляется новый узел (как по-
томок). Он добавляется в сегмент, хранящийся в поле
TreeSegment элементе Segments.
Алгоритм процедуры приведен на рис. 3.55.
428
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Процедура AddNo de Click Лист 1
Всего 1
( Начало )
1. Задание начального значения переменной Net
2. Получение имени узла с помощью диалога InputBox
1, Получение имен сегмента и узла с помощью процедуры
GetNames
2. Получение номеров сегмента и узла с помощью функций
Get Segment Index и GetNodelndex
1. Увеличение количества узлов
2. Изменение длины массива Nodes
3. Заполнение последнего элемента массива Nodes: имя
узла и число тегов
4. Добавление узла с именем узла контроллера в компонент
TreeViewl
Рис. 3.55. Алгоритм процедуры AddNodeClick
429
РАЗРАБОТКА SCADA-СИСТЕМ
AddltemClick
Выполняется добавление узла (имя тега) в окно компонента
TreeViewl и добавление тега в ОРС-сервер. Эта процедура вызы-
вается при щелчке мышью на пункте меню «Добавить тег» пункта
«Тег». При этом вызывается диалог InputBox с именем «Добавле-
ние тега», в поле ввода которого необходимо ввести полное имя
тега, например: Ultranet l.FE.Vxodl. Если имя тега не введено вы-
полняется выход из процедуры по Exit. Далее проверяется значение
переменной nt, значение false которой означает, что ОРС-клиент
расположен на мастере и нет необходимости подключаться к объ-
екту автоматизации. При этом выполняется следующие действия:
- проверяется, запущен ли ОРС-сервер;
- если ОРС-сервер запущен, вызывается процедура GetNames,
которая разделяет полное имя тега на компоненты Segment,
Node и ItemID;
- с помощью функций GetSegmentlndex, GetNodelndex,
Getltemlndex эти строковые имена преобразуются в целые
числа i, j и к соответственно; они являются индексами ди-
намических массивов Segments, Nodes,Items;
- если сегмент и узел с номерами i и j соответственно суще-
ствуют, а добавляемого тега нет, то этот тег добавляется;
при этом увеличивается на единицу значение переменной
ItemsCount, содержащей размерность динамического мас-
сива Items. Процедурой SetLength задается размерность ди-
намического массива Items;
- с помощью функции GroupAddltem происходит добавление
нового тега с заданным именем в заданный узел и сегмент
ОРС-сервера;
- если операция по добавлению тега в ОРС-сервер прошла
успешно, о чем говорит значение true функции Succeeded
(HR), то имя тега запоминается в поле ItemName нового
элемента массива Items; это имя появляется в поле компо-
нента TreeViewl; если операция по добавлению нового тега
в ОРС-сервер прошла неудачно, то необходимо уменьшить
на 1 размер динамического массива Items.
- если значение nt=true, то необходимо работать (принимать
данные) не с ОРС-сервера, а с объекта автоматизации; как
430
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
и ранее определяются значение переменных i, j и к; если
тега с заданным именем в массиве Items нет, то осуществля-
ется считывание с ОА в строковую переменную s всех имен
тегов, ранее добавленных всеми ОРС-клиентами.
Далее выполняется разбитие строковой переменной s на ряд
отдельных имен тегов и помещение этих тегов в динамический мас-
сив ms.
Затем выполняется поиск заданного имени тега в массиве ms.
При этом используется логическая переменная fff, которая изна-
чально устанавливается в false (имя не найдено). Если имя тега,
введенное в InputBox, имеется в массиве ms, то его номер m записы-
вается в поле Number последнего элемента динамического массива
Items. Затем динамический массив ms уничтожается, так как он уже
выполнил свои функции.
Если заданный тег в списке ОА отсутствует (fff=false), то вы-
полняются действия по пересылке тега в ОА, который и добавит
его в ОРС-сервер. В переменной error сохраняется результат этого
добавления.
Затем повторно выполняются действия по чтению в перемен-
ную s списка всех тегов, добавленных в ОРС-сервер и разбивка это-
го списка на отдельные имена тегов, которые сохраняются в мас-
сиве ms. Далее вычисляется порядковый номер добавленного тега
в списке. Затем этот номер записывается в поле Number последнего
элемента массива Items.
Если ошибок в добавлении нового тега в ОРС-сервер нет, то
имя тега добавляется в массив Items и отображается в поле вывода
компонента TreeViewl. В противном случае размерность динамиче-
ского массива Items устанавливается в прежнее состояние.
Алгоритм процедуры приведен на рис. 3.56.
431
РАЗРАБОТКА SCADA-СИСТЕМ
Процедура AddltemClick
Лист 1
Всего 11
Рис. 3.56. Алгоритм процедуры AddltemClick (начало)
432
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Процедура AddltemClick
Лист 2
Рис. 3.56. Алгоритм процедуры AddltemClick (продолжение)
433
РАЗРАБОТКА SCADA-СИСТЕМ
Процедура AddltemCIick Лист 3
Рис. 3.56. Алгоритм процедуры AddltemClick (продолжение)
434
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Рис. 3.56. Алгоритм процедуры AddltemClick (продолжение)
435
РАЗРАБОТКА SCADA-СИСТЕМ
Процедура AddltemClick Лист 5
1. Увеличение значения гчетчика m на едишгцу
1. Переменной fff присваивается значение false
Рис. 3.56. Алгоритм процедуры AddltemClick (продолжение)
436
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Процедура AddltemClick
Лист б
1. Переменной fff присваивается значение false
2. В поле Number последнего элемента массива
Items сохраняется номер найденного тега
Рис. 3.56. Алгоритм процедуры AddltemClick (продолжение)
437
РАЗРАБОТКА SCADA-СИСТЕМ
Процедура AddltemClick
Лист?
Рис. 3.56. Алгоритм процедуры AddltemClick (продолжение)
438
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Процедура AddltemClick
Лист 3
1. Добавление пробела в начало списка
2. Задание количества элементов в динамическом массиве ms
3. Изменение длины динамического массива ms
Рис. 3.56. Алгоритм процедуры AddltemClick (продолжение)
439
РАЗРАБОТКА SCADA-СИСТЕМ
Процедура AddltemClick
Лист 9
Рис. 3.56. Алгоритм процедуры AddltemClick (продолжение)
440
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Процедура AddltemClick
Лист 10
Нет
Рис. 3.56. Алгоритм процедуры AddltemClick (продолжение)
441
РАЗРАБОТКА SCADA-СИСТЕМ
Рис. 3.56. Алгоритм процедуры AddltemClick (окончание)
442
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
DelSegmentClick
Реализованы действия по удалению из окна объекта TreeViewl
и ОРС — сервера заданного сегмента со всеми входящими в него
узлами и тегами. Алгоритм процедуры приведен на рис. 3.57. При
помощи диалога InputBox в переменную Seg записывается имя уда-
ляемого сегмента. Если имя сегмента введено, то выполняются сле-
дующие действия:
- запрещается работа таймера Timeri;
- очищаются поля компонентов ItemValue и ItemQuality;
- вычисляется номер удаляемого сегмента в массиве Segments;
- если удаляемый сегмент существует в массиве Segments,
то выполняются следующие действия:
• с помощью функции GroupRemoveltem удаляются все
теги, входящие в удаляемый сегмент;
• с помощью процедуры Server.RemoveGroup удаляется
сегмент;
• из компонента TreeViewl удаляется узел с именем
сегмента и соответственно все входящие в него узлы
с именами узлов и тегов;
• производится сдвиг всех сегментов массива Segments
на один влево (к началу массива);
- уменьшается количество сегментов в массиве Segments;
- устанавливается длина динамического массива Segments
в новое значение (SegmentsCount), т. е. из массива удаляется
последний элемент.
443
РАЗРАБОТКА SCADA-СИСТЕМ
Процедура DelSegprentClick
Лист 1
Всего?
1. Задание начального значения переменной Seg
2. Получение имени сегмента с помощью диалога InputBox
1. Запрещение работы таймера
2. Задание начальных значений свойства Text компонентов ItemValue
и ItemQuality
З. Получение номера сегмента с помощью функции GetSegmentlndex
Рис. 3.57. Алгоритм процедуры DelSegmentClick (начало)
444
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Процедура DelSegmentCIick
Лист 2
Рис. 3.57. Алгоритм процедуры DelSegmentClick (продолжение)
445
РАЗРАБОТКА SCADA-СИСТЕМ
Процедура DelSegmentClick Лист з
1. Удаление j-го тега массива Items из ОРС- сервера с помощью
функции GroupRemoveltem
L Увеличение счетчика j на единицу
1. Удаление сегмента из ОРС - сервера с помощью функции
RcmoveGroup
2. Удаление узла с именем сегмента из компонента TreeViewl
Рис. 3.57. Алгоритм процедуры DelSegmentClick (продолжение)
446
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Процедура DelSegmentClick Лист 4
1. Задание начального значение счетчика i (n_Segment)
1. Запись i+1 элемента массива Segments на место i-го элемента,
т.е. полей элемента: имя сегмента SegmentName, интерфейс
Segment, хэндл сегмента SegmentHandle, узел в компоненте
TreeViewl TreeSegment, количество узлов в массиве Nodes,
2. Изменение длины мае сива Nodes
Рис. 3.57. Алгоритм процедуры DelSegmentClick (продолжение)
447
РАЗРАБОТКА SCADA-СИСТЕМ
Процедура DelSegmentClick Лист 5
1. Запись j+ 1-го элемента массива Nodes на место j -го элемента, т. е. полей:
имя узла NodeName, число тегов ItcmsCount, узел в компоненте TreeViewl
TreeNode 2, Изменение длины динамического массива Nodes
Рис. 3.57. Алгоритм процедуры DelSegmentClick (продолжение)
448
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Процедура DelSegmentClick
Лист б
I
1. Запись к+1 -го элемента массива Items на место к ~го элемента, т.е.
полей: имя тега ItemName, хэндл тега ItemHandle, узел в
компоненте TreeViewl Treeitem, тип тега ItemType
1. Увеличение значения счетчика к на единицу
1. Увеличение счетчика i на единицу
1. Увеличение счетчика i на единицу
Рис. 3.57. Алгоритм процедуры DelSegmentClick (продолжение)
449
РАЗРАБОТКА SCADA-СИСТЕМ
Рис. 3.57. Алгоритм процедуры DelSegmentClick (окончание)
DelNodeClick
Алгоритм процедуры приведен на рис. 3.58.
В процедуре DelNodeClick осуществляется удаление из компо-
нента TreeViewl элемента с именем узла контроллера. В перемен-
ную Nd при помощи диалога InputBox записывается полное имя
удаляемого узла контроллера (Сегмент +Узел). Если имя узла кон-
троллера введено, то выполняются следующие действия:
- запрещается работа таймера Timeri;
- очищаются поля компонентов ItemValue и ItemQuality;
- с помощью процедуры GetNames извлекаются имена сег-
мента и узла (контроллера) из полного имени узла (контрол-
лера) (Nd);
- вычисляются порядковый номер сегмента n Segment в мас-
сиве Segments и порядковый номер узла n Node в массиве
Nodes;
- если сегмент и узел существуют в массивах Segments
и Nodes, то выполняются следующие действия:
• удаляются все теги, входящие в этот узел с помощью
функции GroupRemoveltem;
• удаляется узел в компоненте TreeViewl с именем узла
(контроллера) и все узлы с именами тегов, входящие
в него;
450
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
• производится сдвиг всех элементов массива Nodes на
один влево (к началу массива);
- уменьшается число узлов в массиве Nodes;
- длина массива Nodes устанавливается в новое значение.
Процедура DelNocleClick
Лист 1
Всего 5
Рис. 3.58. Алгоритм процедуры DelNodeClick (начало)
451
РАЗРАБОТКА SCADA-СИСТЕМ
Рис. 3.58. Алгоритм процедуры DelNodeClick (продолжение)
452
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Процедура DeiNode Click
Лист 3
Рис. 3.58. Алгоритм процедуры DelNodeClick (продолжение)
453
РАЗРАБОТКА SCADA-СИСТЕМ
Процедура DelNodeClick
1. Задание начального значения счетчика к
1. Запись к+ 1-го элемента массива Items на место
к -го элемента, т.е. полей элемента: имя тега,
ItemName, хэндл тега ItemsHandle, узел в
компоненте TreeViewl и тип тега ItemType
1. Увеличение значения счетчика к на единицу
L Увеличение значения счетчика j на единицу
Рис. 3.58. Алгоритм процедуры DelNodeClick (продолжение)
454
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Да
Процедура DelNodeClick
Лист 4
7
3
Количество тегов
^оавно нулю?^
Нет
1. Задание начального значения счетчика к
Значение счетчика4
k<!lemsCount-I?
Нет
Да
1. Запись к+ 1-го элемента массива Items на место
к -гр элемента, т.е. полей элемента: имя тега,
ItemName, хэндл тега ItemsHandle, узел в
компоненте TreeViewl и тип тега ItemType
1. Увеличение значения счетчика к на единицу
1. Увеличение значения счетчика j на единицу
Рис. 3.58. Алгоритм процедуры DelNodeClick (окончание)
455
РАЗРАБОТКА SCADA-СИСТЕМ
DelltemClick
Алгоритм процедуры приведен на рис. 3.59.
Процедура DelltemClick
Лист 1
Всего 3
Рис. 3.59. Алгоритм процедуры DelltemClick (начало)
456
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Процедура DelltemCbck
Лист 2
Рис. 3.59. Алгоритм процедуры DelltemClick (продолжение)
457
РАЗРАБОТКА SCADA-СИСТЕМ
Лист 3
Рис. 3.59. Алгоритм процедуры DelltemClick (окончание)
В процедуре DelltemClick осуществляется удаление тега из ОРС-
сервера и узла с именем тега из компонента TreeViewl. В перемен-
ную Itm вводится полное имя удаляемого тега (Сегмент+Узел+Тег).
Если имя тега введено, то выполняются следующие действия:
- запрещается работа таймера;
- очищаются поля компонентов ItemValue и ItemQuality;
- с помощью процедуры GetNames из полного имени тега
формируются составляющие и помещаются в переменные
Segment, Node и Item;
- определяются порядковые номера сегмента, узла и тега в
массивах Segments, Nodes и Items;
- если сегмент, узел и тег существуют, то выполняются сле-
дующие действия:
• удаляется узел с именем узла из компонента TreeViewl;
• с помощью функции GroupRemoveltem удаляется тег из
ОРС-сервера;
• происходит сдвиг всех тегов в массиве Items на один
влево (к началу массива);
- в динамическом массиве Items уменьшается количество тегов:
- длина массива Items устанавливается в новое значение.
TreeViewlClick
Алгоритм процедуры приведен на рис. 3.60.
В процедуре TreeViewlClick реализуется поиск в структу-
ре массива Segments, выделенного тега в компоненте TreeViewl
458
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
(свойство Selected). Затем его координаты сохраняются в перемен-
ные SegmentNumber, NodeNumber и ItemNumber.
TimeriTimer
Алгоритм процедуры приведен на рис. 3.61.
Процедура TMainForm.TimerlTimer предназначена для считы-
вания из ОРС-сервера значения тега и качества связи.
Процедура TreeViewClick
Рис. 3.60. Алгоритм процедуры TreeViewiClick (начало)
459
РАЗРАБОТКА SCADA-СИСТЕМ
460
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Рис. 3.60. Алгоритм процедуры TreeViewlClick (окончание)
461
РАЗРАБОТКА SCADA-СИСТЕМ
Рис. 3.61. Алгоритм процедуры TimeriTimer (начало)
462
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Лист 2
Процедура TiinerlTiiner
Рис. 3.61. Алгоритм процедуры TimenTimer (продолжение)
463
РАЗРАБОТКА SCADA-СИСТЕМ
Лист 3
Процедура TimerlTiiner
Рис. 3.61. Алгоритм процедуры TimenTimer (продолжение)
464
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Процедура TiinerlTiiner
Лист 4
Рис. 3.61. Алгоритм процедуры TimeriTimer (окончание)
Имена тега, узла и сегмента будут взяты из переменных
ItemNumber, NodeNumber, SegmentNumber. Эти имена вычисляются
в процедуре TMainForm.TreeViewlClick, вызываемой при щелчке
мышью на каком-либо узле дерева TreeViewl.
С помощью функции ReadOPCGroupItemValue из ОРС-сервера
читается значение ItemValue тега с порядковым номером ItemNumber
в массиве Items и качество связи тега ItemQuality.
Далее рассматривается значение переменной HR. Если значе-
ние функции Succeeded(HR)=true, то значение тега считано успеш-
но. Если тег имеет тип Float, то в поле компонента ItemValue выво-
дится преобразованное числовое значение тега.
465
РАЗРАБОТКА SCADA-СИСТЕМ
Если тег имеет любой другой тип, то его значение выводится
в поле компонента ItemValue без преобразования.
Затем выполнятся проверка качества приема тега из сети и в
поле компонента ItemQaulity выводятся строки Good («хорошо»)
или Bad («плохо»).
Если ОРС-клиент запущен с удаленного компьютера сети
Ethernet, в которую включен мастер, то реализуются несколько дру-
гие действия.
Здесь NetServer — это интерфейс для связи с объектом авто-
матизации. Объект автоматизации — приложение, реализованное
в Delphi и расположенное на мастере. Оно предназначено для обме-
на данными между ОРС-сервером и ОРС-клиентами сети Ethernet,
запуска ОРС-сервера, приема информации (тегов) и передачу их
значений в адрес ОРС-клиента, расположенного на удаленном ком-
пьютере (Slave).
В переменную Itms считывается значение NetServer.Itms, ко-
торое представляет собой строку, в которую через пробел записа-
ны значения всех тегов. Затем значение тега, выделенного в окне
TreeViewl, передается в поле вывода компонента ItemValue.
SaveClick
Алгоритм процедуры приведен на рис. 3.62.
- В процедуре SaveClick происходит сохранение структуры
массива Segments с помощью диалога SaveDialogl. При
этом выполняются следующие действия:
- определяется фильтр для диалога SaveDialogl, т. е. тип фай-
лов, которые будут доступны;
- определяется каталог, который откроется по умолчанию
в компоненте SaveDialogl;
- если пользователь нажал кнопку «Сохранить», то выполня-
ются следующие действия:
• проверяется, соответствует ли тип выбранного файла
типу, указанному в фильтре, и в переменную fhame за-
писывается полное имя сохраняемого файла;
• в выбранный файл записывается структура массива
Segments.
466
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Лист 1
Всего 4
Процедура SaveClick
Рис. 3.62. Алгоритм процедуры SaveClick (начало)
467
РАЗРАБОТКА SCADA-СИСТЕМ
Лист 2
Процедура Save Click
Рис. 3.62. Алгоритм процедуры SaveClick (продолжение)
468
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
ЛистЗ
Процедура SaveClick
1. Запись имени узла и количества тегов в файл
1. Задание начального значения счетчика к
1. Запись имени i-го тега в файл
1. Увеличение значения счетчика к на единицу
Рис. 3.62. Алгоритм процедуры SaveClick (продолжение)
469
РАЗРАБОТКА SCADA-СИСТЕМ
Процедура SaveClick
Лист 4
Рис. 3.62. Алгоритм процедуры SaveClick (окончание)
470
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
LoadClick
Выполняются обратные SaveClick действия: конфигурация сети,
хранящаяся в файле, будет выводиться в окно объекта TreeViewl.
Алгоритм процедуры приведен на рис. 3.63. В процедуре происхо-
дит чтение структуры массива Segments из файла, восстановление
этой структуры в компоненте TreeViewl, запуск ОРС-сервера и до-
бавление в него сегментов и тегов. При этом выполняются следую-
щие действия:
- определяется фильтр для компонента OpenDialogl, т. е. тип
файлов, которые будут доступны;
- определяется каталог, который откроется по умолчанию
в компоненте OpenDialogl;
- если пользователь нажал на кнопку «Открыть», то выпол-
няются следующие действия:
• запускается ОРС-сервер, если не был запущен ранее;
• разрешается работа пункта меню «Стоп» и запрещается
«Пуск»;
• удаляются все узлы в компоненте TreeViewl;
• обнуляется динамический массив Segments;
• полное имя открываемого файла записывается в пере-
менную fname;
• читается структура массива Segments и загружается
в компонент TreeViewl;
• добавляются сегменты и теги в ОРС-сервер;
• разрешается работа пунктов меню «Добавить сегмент
UltraNet», «Удалить сегмент UltraNet», «Добавить узел»,
«Удалить узел», «Добавить тег» и «Удалить тег».
471
РАЗРАБОТКА SCADA-СИСТЕМ
Лист 1
Всего 5
Процедура LoadClick
Рис. 3.63. Алгоритм процедуры LoadClick (начало)
472
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Лист 2
Процедура Load Click
Рис. 3.63. Алгоритм процедуры LoadClick (продолжение) TreeViewl
473
РАЗРАБОТКА SCADA-СИСТЕМ
Лист 3
Процедура Load Click
1. Чтение имени узла из файла
2. Добавление узла с именем узла в компонент TreeViewl
3. Чтение количества тегов из файла
4. Изменение длины динамического массива Items
Рис. 3.63. Алгоритм процедуры LoadClick (продолжение)
474
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Процедура LoadClick
1. Чтение имени тега из файла
2. Добавление тега в ОРС - сервер с помощью функции
GroupAddltem
3. Добавление элемента с именем узла в компонент TreeViewl
1. Увеличение значения счетчика к на единицу
I
1. Увеличение значения счетчика j на единицу
1. Увеличение значения счетчика i на единицу
Рис. 3.63. Алгоритм процедуры LoadClick (продолжение)
475
РАЗРАБОТКА SCADA-СИСТЕМ
ExtClick
Реализуется выход из приложения по пункту меню «Выход» в
MainMenu. Алгоритм процедуры приведен на рис. 3.64. Процедура
запускается при щелчке мышью на пункте меню «Выход». Выпол-
няются следующие действия:
- выключается ОРС-сервер;
- отключение от объекта автоматизации;
- завершение работы приложения.
Процедура ExtClick
Рис. 3.64. Алгоритм процедуры ExtClick
Лист 1
Всего 1
FormClose
Выполняются действия по закрытию приложения. Алгоритм
процедуры приведен на рис. 3.65. В процедуре выполняются следу-
ющие действия:
476
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
- ликвидируется компонент MainMenu;
- ОРС-клиент отключается от объекта автоматизации;
- ликвидируется динамический массив Segment;
- завершается работа ОРС-сервера (Server:=nil).
Процедура FonnClose
Начало
Лист 1
Всего 1
1. Уничтожение главного меню
2. Отключение от объекта автоматизации
3. Уничтожение массива Segments
4. Отключение от ОРС - сервера
5. Запись в переменную fhame полного имени файла sys.sy
6. Связь файловой переменной f с файлом
7. Перезапись файла sys. sy
8. Запись в файл имели ОРС-сервера
9. Запись в файл имени объекта автоматизации
10, Запись в файл имени хоста
11. Запись в файл IP-адреса хоста
12. Закрытие файла
Конец
Рис. 3.65. Алгоритм процедуры FormClose
Далее идет раздел описания типов TItem, TNode и TSegment.
Функции, использующиеся в процедурах
GetltemType
Возвращает в строковой форме тип тега ItemValue, представ-
ленного в строковом виде. Алгоритм функции приведен на рис. 3.66.
GetSegmentlndex
Отыскивает в массиве Segments элемент Segment и возвращает
его номер. Алгоритм функции приведен на рис. 3.67.
GetNodelndex
Отыскивает в массиве Segment узел с именем Node, входящий
в сегмент с именем Segment, и возвращает его номер. Алгоритм
функции приведен на рис. 3.68.
477
РАЗРАБОТКА SCADA-СИСТЕМ
Getltemlndex
Отыскивает в массиве Segment тег с именем ItemID, входящий
в узел Node, который, в свою очередь, входит в сегмент Segment
и возвращает его номер. Алгоритм функции приведен на рис. 3.69.
GetNames
Предназначена для преобразования строковой константы Path
в ряд строковых переменных: Segment, Node, ItemID. Алгоритм
процедуры приведен на рис. 3.70.
Рис. 3.66. Алгоритм функции GetltemType (начало)
478
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Рис. 3.66. Алгоритм функции GetltemType (окончание)
479
РАЗРАБОТКА SCADA-СИСТЕМ
Лист 1
Функция Ge (Segment Index
Рис. 3.67. Алгоритм функции GetSegmentlndex
480
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Процедура GetNo de Index
Лист 1
Всего 2
Рис. 3.68. Алгоритм процедуры GetNodelndex (начало)
481
РАЗРАБОТКА SCADA-СИСТЕМ
Рис. 3.68. Алгоритм процедуры GetNodelndex (окончание)
482
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Функция Get Item Index
Лист 1
Рис. 3.69. Алгоритм функции Getltemlndex (начало)
483
РАЗРАБОТКА SCADA-СИСТЕМ
Рис. 3.69. Алгоритм функции Getltemlndex (окончание)
484
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Рис. 3.70. Алгоритм процедуры GetNames (начало)
485
РАЗРАБОТКА SCADA-СИСТЕМ
Процедура GetNames Лист 2
Рис. 3.70. Алгоритм процедуры GetNames (окончание)
Описание глобальных переменных приложения
MainForm: TMainForm описывает главную форму приложе-
ния.
HR:HRESULT описывает результат добавления элемента
(сегмента или тега) в ОРС-сервер.
Server: lOPCServer — интерфейс для связи с ОРС-сервером.
NetServer: Variant — интерфейс для связи с объектом авто-
матизации, который запускается с удаленного компьютера сети при
условии, что на мастере запущена утилита scktsrvr.exe (входит в со-
став утилит Delphi).
486
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Segments: array of TSegment представляет собой динамиче-
ский массив элементами, которого являются записи типа TSegment,
рассмотренного выше.
SegmentsCount: TOleEnum содержит текущее число сегмен-
тов сети.
SegmentNumber, NodeNumber, ItemNumber: TOleEnum
представляют собой номера сегмента, узла и тега, выделенного
щелчком мыши в компоненте TreeViewl.
Nt: Boolean — признак режима работы с сетью Ethernet:
«1 мастер — несколько клиентов» или «1 мастер — 1 клиент».
MainMenu: TMainMenu — основное меню формы, содержа-
щее пункты:
- F:TMenuItem — «Файл»;
- Segment: TMenuItem — «Сегмент Ultranet»;
- Node: TMenuItem — «Узел»;
- Item: TMenuItem — «Тег»;
- Load : TMenuItem — «Открыть»;
- Save: TMenuItem — «Сохранить»;
- Connect: TMenuItem — «Пуск»;
- Disconnect: TMenuItem — «Стоп»;
- Ext: TMenuItem — «Выход»;
- AddSegment: TMenuItem — «Добавить сегмент Ultranet»;
- DelSegment: TMenuItem — «Удалить сегмент Ultranet»;
- AddNode: TMenuItem — «Добавить узел»;
- DeiNode: TMenuItem — «Удалить узел»;
- Additem: TMenuItem — «Добавить тег»;
- Delltem: TMenuItem — «Удалить тег»;
- Local: TMenuItem — «ОРС-сервер»;
- Remote: TMenuItem — «Automation Object».
Листинг 3.4
unit Main;
interface
uses
Windows, Messages, Syslltils, Variants, Classes, Graphics,
487
РАЗРАБОТКА SCADA-СИСТЕМ
Controls, Forms, Dialogs, StdCtrls, ComObj, MConnect,
SConnect, DB, DBCIient, ComCtrls, ExtCtrls, ActiveX,
OPCDA, OPCTypes, OPCUtils, Menus;
type
TMainForm = class(TForm)
//компонент для отображения иерархии данных в виде
//дерева, в котором пользователь может выбрать нужный
// ему узел или узлы
TreeViewl: TTreeView;
//таймер
Timen: TTimer;
//стандартный диалог для сохранения
//настроек программы
SaveDialogi: TSaveDialog;
//стандартный диалог для загрузки настроек программы
Open Dialogi:TOpen Dialog;
//компонент для связи клиента с сервером
// с помощью TCP/IP
SocketConnectioni:TSocketConnection;
//компонент для ввода имени мастера
HostName: TLabeledEdit;
//компонент для ввода IP-адреса мастера
HostIP: TLabeledEdit;
//компонент для ввода имени ОРС-сервера
OPCServer: TLabeledEdit;
//компонент для ввода имени Automation Object
NServer: TLabeledEdit;
//компонент для отображения качества значения тега
ItemQuality: TLabeledEdit;
//компонент для отображения значения выбранного тега
ItemValue: TLabeledEdit;
//компонент для группировки компонентов
GroupBoxi: TGroupBox;
//компонент для группировки компонентов
GroupBox2: TGroupBox;
//компонент для группировки компонентов
GroupBox3: TGroupBox;
//действия при создании формы
procedure FormCreate(Sender: TObject);
//действия, вызванные щелчком на пункте меню «ОРС-сервер»
488
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
procedure Loca I Cl ick(Sen der: TObject);
//действия, вызванные щелчком на пункте меню
//Automation Object
procedure RemoteClick(Sender: TObject);
//действия, вызванные щелчком на пункте меню «Стоп»
procedure DisconnectClick(Sender: TObject);
//действия, вызванные щелчком на пункте меню
// «Добавить сегмент UltraNet»
procedure AddSegmentClick(Sender: TObject);
//действия, вызванные щелчком на пункте меню
//«Добавить узел»
procedure AddNodeClick(Sender: TObject);
//действия, вызванные щелчком на пункте меню
//«Добавить тег»
procedure AddltemClick(Sender: TObject);
//действия, вызванные щелчком на пункте меню
И «Удалить сегмент UltraNet»
procedure DelSegmentClick(Sender: TObject);
//действия, вызванные щелчком на пункте меню
// «Удалить узел»
procedure DelNodeClick(Sender:TObject);
//действия, вызванные щелчком на пункте меню
//«Удалить тег»
procedure DelltemClick(Sender:TObject);
//действия, вызванные щелчком на компоненте TreeViewl
procedure TreeViewiClick(Sender: TObject);
//реакция на сигналы таймера
procedure TimenTimer(Sender: TObject);
//действия, вызванные щелчком на пункте меню «Сохранить»
procedure SaveClick(Sender: TObject);
//действия, вызванные щелчком на пункте меню «Открыть»
procedure Load Cl ick(Send er: TObject);
//действия, вызванные щелчком на пункте меню «Выход»
procedure ExtCIick(Sender: TObject);
//действия при закрытии формы
procedure FormClose(Sender: TObject; var Action:
TCIoseAction);
private
{Private declarations}
public
489
РАЗРАБОТКА SCADA-СИСТЕМ
{Public declarations}
end;
type
И тег
Tltem=record
// имя тега
ltemName:string;
//хэндл тега
ltemHandle:OPCHANDLE;
//тип тега
ItemTypeiTVarType;
//значение тега
ltemValue:string;
//качество связи тега
ltemQuality:word;
//узел в KOMnoHenmeTreeViewi
Treeitem :TTreeNode;
//порядковый номер тега в списке тегов,
//получаемый от Automation Object
Number:integer;
end;
//узел
TNode=record
// имя узла
NodeName:string;
//количество тегов в узле
ltemsCount:TOIeEnum;
//массив тегов
ltems:array of TItem;
//узел в KOMnoHenmeTreeViewi
TreeNode:TTreeNode;
end;
//сегмент
TSegment=record
// имя сегмента
SegmentName:string;
//интерфейс, осуществляющий
//добавление и удаление тегов в сегмент
Segment: lOPCItemMgt;
490
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
И хэндл сегмента
SegmentHandle:OPCHANDLE;
//количествоузлов в сегменте
NodesCount:TOIeEnum;
//массив узлов
Nodes:array of TNode;
//узел в компоненте TreeViewl
TreeSegment:TTreeNode;
end;
//функция, возвращающая тип тега по его значению
function GetltemType(ltemValue:string):string;
//функция, возвращающая номер сегмента в массиве
//Segments по имени сегмента
function GetSegmentlndex(Segment:string):TOIeEnum;
//функция, возвращающая номер узла в массиве
//Nodes по имени узла
function GetNodelndex(SegmentzNode:string):TOIeEnum;
//функция, возвращающая номер тега в массиве
//Items по имени тега
function Getltemlndex(SegmentzNode,ItemID:string):
TOleEnum;
//процедура, возвращающая имя сегмента, узла и тега
//по полному имени тега
procedure GetNames(Path:string;var SegmentzNodez
Item ID:string);
var
//главная форма
M a i n Form: TM a i n Form;
//переменная, хранящая результат добавления
// или удаления тега или сегмента в ОРС-сервер
HR:HRESULT;
//интерфейс для связи с ОРС-сервером
ServerdOPCServer;
//интерфейс для связи с Automation Object
NetServer:Variant;
491
РАЗРАБОТКА SCADA-СИСТЕМ
И массив сегментов
Segments:array of TSegment;
//количество сегментов
SegmentsCount:TOIeEnum;
//текущие номер сегмента, узла и тега
//выделенные пользователем в TreeViewl
SegmentNumberzNodeNumberJtemNumber:TOIeEnum;
//признакработы приложения:
//false — работа с ОРС-сервером
//true — работа с Automation Object
Nt:boolean;
// главное меню
М a i n М е п и :Т М a i n М е п и;
//пункт меню «Файл»
F:TMenultem;
//пункт меню Сегмент UltraNet
Segment:TMenultem;
//пункт меню «Узел»
Node:TMenultem;
//пункт меню «Тег»
Item :TMenu Item;
//пункт меню «Открыть»
Load:TMenultem;
//пункт меню «Сохранить»
Save:TMenultem;
//пункт меню «Пуск»
Connect:TMenultem;
//пункт меню «Стоп»
Disconnect:TMenultem;
//пункт меню «Выход»
Ext:TMenultem;
//пункт меню «Добавить сегмент UltraNet»
AddSegment:TMenultem;
//пункт меню «Удалить сегмент UltraNet»
DelSegment:TMenultem;
//пункт меню «Добавитьузел»
AddNode:TMenultem;
//пункт меню «Удалитьузел»
DelNode:TMenultem;
//пункт меню «Добавить тег»
Add Item :TMenultem;
//пункт меню «Удалитьузел»
Del Item :TMenultem;
492
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
//пункт меню «ОРС-сервер»
Local :ТМеп и Item;
//пункт меню Automation Object
Rem ote :ТМ е п и Ite m;
//текущая директория
CurrDir:string;
//директория приложения
Dinstring;
implementation
{$R *.dfm}
//функция, возвращающая тип тега по его значению
function GetltemType(ltemValue:string):string;
var
//счетчики
i,s:byte;
begin
//начальный результат функции
Result:='Timer';
//если значение тега TRUE или FALSE
if (UpperCase(ltemValue)=/TRUE/) or
(UpperCase(ltemValue)=/FALSE/)
then
begin
//тег имеет тип Boolean
Result:='Boolean';
//выход из функции
exit;
end;
//проверка всех символов значения тега
for i:=1 to Length(ltemValue) do
// если нашли точку или запятую
if (ltemValue[i]=7) or (ItemVaIue[i]')
then
begin
//тег имеет тип Real
Result:='Float';
//выход из функции
exit;
end;
//начальное значение счетчика
493
РАЗРАБОТКА SCADA-СИСТЕМ
S:=O;
//проверка всех символов значения тега
for i:=i to Length(ltemValue) do
// если нашли цифру или знак плюс или минус
if ltemValue[i] in [чо717273//Ч75///67778797"7+/] then
//увеличиваем значение счетчика
inc(s);
//если значение счетчика совпадает
//с количеством символов значения тега
if s=l_ength(ltemValue)
then
begin
//тег имеет тип Integer
Resu It:='l nteger';
//выход из процедуры
exit;
end;
end;
//функция, возвращающая номер сегмента в массиве
//Segments по его имени
function GetSegmentlndex(Segment:string):TOIeEnum;
var
//счетчик
i:TOIeEnum;
begin
//начальное значение
Result:=-i;
// если количество сегментов не равно нулю
if SegmentsCountoo then
//цикл по всем сегментам
for i:=о to SegmentsCount-i do
//если нашли нужный сегмент
if Segments[i].SegmentName=Segment
then
begin
//номер сегмента
Result:=i;
//выход из цикла
Break;
end;
end;
494
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
//функция, возвращающая номер узла в массиве
//Nodes по имени узла
function GetNodelndex(Segmentf Node:string):TOIeEnum;
var
//счетчики
iJiTOIeEnum;
begin
//начальное значение
Result:=-i;
//номер сегмента
i:=GetSegmentlndex(Segment);
// если номер сегмента не равен минус единице
if io-i then
with Segments[i] do
// если количество узлов не равно нулю
if NodesCountoo
then
//цикл по количеству узлов
for j:=o to NodesCount-i do
// если нашли нужный узел
if Nodes[j].NodeName=Node
then
begin
// номер узла
Result:=j;
//выход из цикла
Break;
end;
end;
//функция, возвращающая номер тега в массиве
//Items по имени тега
function Getltemlndex(SegmentfNodeJtemlD:string):
TOIeEnum;
var
//счетчики
izjzk:TOIeEnum;
begin
//начальное значение
Result:=-i;
//номер сегмента
i:=GetSegmentlndex(Segment);
495
РАЗРАБОТКА SCADA-СИСТЕМ
// номер узла
j:=GetNodelndex(SegmentzNode);
И если номер сегмента и узла не равны минус единице
if (io-i) and (jo-i)
then
with Segments[i].Nodes[j] do
//если количество тегов не равно нулю
if ItemsCountoo
then
//цикл по количеству тегов
for к:=о to ItemsCount-i do
// если нашли нужный тег
if ltems[k].ltemName=ltemlD
then
begin
//номер тега
Result:=l<;
//выход из цикла
Break;
end;
end;
//функция, возвращающая имя сегмента, узла и тега
//по полному имени тега
procedure GetNames(Path:string;var SegmentfNodef
ltemlD:string);
var
//счетчики
i,j:byte;
begin
// если полное имя тега не пусто
if Length(Path)oo
then
begin
//начальное значение
j-o;
//цикл по всем символам имени тега
for i:=1 to Length(Path) do
// если i символ точка
if Path[i]=7
then
//увеличение счетчика
496
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
inc(j)
И в любом другом случае
else
//получение имени сегмента, узла и тега
casej of
o:Segment:=Segment+Path[i];
i:Node:=Node+Path[i];
2:ltemlD:=ltemlD+Path[i];
end;
end;
end;
//динамическое создание пунктов основного меню,
// всех подменю и назначение процедур для подменю
procedure TMainForm.FormCreate(Sender: TObject);
var
//файловая переменная
_f:TextFile;
//полное имя файла sys.sy, в котором хранятся имена
//серверов, имя и IP-адрес мастера
fname:string;
//строковая переменная для считывания значений
//из файла sys.sy
s:string;
begin
//сохранение текущей директории
CurrDir:=GetCurrentDir;
//сохранение директории приложения
Dir:=CurrDir;
// заголовок формы
Main Form. Caption ^'ОРС-клиент';
//создание главного меню
Main Menu:=TMain Menu. Create(Self);
//создание пункта «Файл» в меню
F:=TMenultem.Create(Self);
//заголовок пункта меню
Р.СарЬоп:='Файл';
//создание пункта «Сегмент UltraNet» в меню
Segment:=TMenultem.Create(Self);
//заголовок пункта меню
497
РАЗРАБОТКА SCADA-СИСТЕМ
Segment.Caption ^'Сегмент UltraNet7;
//создание пункта «Узел» в меню
Node:=TMenultem.Create(Self);
//заголовок пункта меню
Node.Caption :='Узел';
//создание пункта «Тег» в меню
ltem:=TMenultem.Create(Self);
//заголовок пункта меню
ltem.Caption:='Ter';
//добавление пунктов меню в главное меню
//добавление пункта «Файл» в меню
Main Menu. Items. Add(F);
//добавление пункта «Сегмент» в меню
Main Menu. Items. Add(Segment);
//добавление пункта «Узел» в меню
Main Menu. Items. Add(Node);
//добавление пункта «Тег» в меню
Main Menu. Items. Add(ltem);
//создание пункта «Открыть» в меню
Load:=TMenultem.Create(Self);
//заголовок пункта меню
Load. Caption :='Открыть...';
//прозрачный цвет картинки
Load.Bitmap.TransparentColor:=clWhite;
//признак отображения прозрачного цвета
Load.Bitmap.Transparent:=true;
//загрузка картинки из файла
Load. Bitmap. Load From File(CurrDir+'\Pictures\Open. bmp');
//создание пункта «Сохранить» в меню
Save:=TMenultem.Create(Self);
//заголовок пункта меню
Save.Caption ^'Сохранить...';
//прозрачный цвет картинки
Save.Bitmap.TransparentColor:=clWhite;
//признак отображения прозрачного цвета
Save.Bitmap.Transparent:=true;
//загрузка картинки из файла
Save. Bitmap. Load From File(CurrDir+'\Pictures\Save.bmp');
//создание пункта «Пуск» в меню
Connect:=TMenultem.Create(Self);
//заголовок пункта меню
Connect.Caption :='Пуск';
498
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
//прозрачный цвет картинки
Connect. Bitmap.TransparentColor:=cl White;
//признак отображения прозрачного цвета
Connect. Bitmap.Transparent:=true;
//загрузка картинки из файла
Connect. Bitmap. Load From File(CurrDir+'\Pictures\Start. bmp');
//создание пункта «Стоп» в меню
Disconnect:=TMenultem.Create(Self);
//заголовок пункта меню
Disconnect.Caption:='CTon';
//прозрачный цвет картинки
Disconnect. Bitmap. TransparentColor:=clWhite;
//признак отображения прозрачного цвета
Disconnect. Bitmap. Transparent:=true;
//загрузка картинки из файла
Disconnect. Bitmap. Load From File(CurrDir+
'\Pictures\Stop.bmp');
//создание пункта «Выход» в меню
Ext:=TMenultem.Create(Self);
//заголовок пункта меню
Ext.Caption:='BbixoA...';
//прозрачный цвет картинки
Ext. Bitmap.TransparentColor:=cl White;
//признак отображения прозрачного цвета
Ext.Bitmap.Transparent:=true;
//загрузка картинки из файла
Ext. Bitmap. Load From File(CurrDir+'\Pictures\Exit.bmp');
//добавление пунктов меню в главное меню
//добавление пункта «Открыть» в меню
F.Add(Load);
//добавление пункта «Сохранить» в меню
F.Add(Save);
//добавление пункта «Пуск» в меню
F.Add(Connect);
//добавление пункта «Стоп» в меню
F.Add(Disconnect);
//добавление пункта «Выход» в меню
F.Add(Ext);
//создание пункта «Добавить сегмент UltraNet» в меню
AddSegment:=TMenultem.Create(Self);
//заголовок пункта меню
AddSegment.Сар^оп:='Добавить сегмент UltraNet';
499
РАЗРАБОТКА SCADA-СИСТЕМ
//прозрачный цвет картинки
AddSegment. Bitmap.TransparentColor:=cl White;
//признак отображения прозрачного цвета
AddSegment. Bitmap.Transparent:=true;
//загрузка картинки из файла
AddSegment. Bitmap. Load From File(CurrDir+
'\Pictures\Add.bmp');
//создание пункта «Удалить сегмент UltraNet» в меню
DelSegment:=TMenultem.Create(Self);
//заголовок пункта меню
DelSegment.Caption^'Xa^MTb сегмент UltraNet7;
//прозрачный цвет картинки
DelSegment.Bitmap.TransparentColor:=cl White;
//признак отображения прозначного цвета
DelSegment.Bitmap.Transparent:=true;
//загрузка картинки из файла
DelSegment. Bitmap. Load From File(CurrDir+
'\Pictures\Del.bmp');
//добавление пунктов меню в главное меню
//добавление пункта «Добавить сегмент UltraNet» в меню
Segment. Add(AddSegment);
//добавление пункта «Удалить сегмент UltraNet» в меню
Segment. Add(DelSegment);
//создание пункта «Добавитьузел» в меню
AddNode:=TMenultem.Create(Self);
//заголовок пункта меню
Add Node.Caption ^'Добавить узел7;
//прозрачный цвет картинки
Add Node. Bitmap.TransparentColor:=cl White;
//признак отображения прозрачного цвета
Add Node. Bitmap.Transparent:=true;
//загрузка картинки из файла
AddNode. Bitmap. Load From File(CurrDir+
'\Pictures\Add.bmp7);
//создание пункта «Удалитьузел» в меню
DelNode:=TMenultem.Create(Self);
//заголовок пункта меню
DelNode.Caption:=7y/]^MTb узел7;
//прозрачный цвет картинки
Del Node.Bitmap.TransparentColor:=clWhite;
//признак отображения прозрачного цвета
Del Node. Bitmap.Transparent:=true;
500
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
//загрузка картинки из файла
Del Node. Bitmap. Load From File(CurrDir+'\Pictures\Del. bmp');
//добавление пунктов меню в главное меню
//добавление пункта «Добавитьузел» в меню
Node. Add(Add Node);
//добавление пункта «Удалитьузел» в меню
Node. Add(Del Node);
//создание пункта «Добавить тег» в меню
Addltem:=TMenultem.Create(Self);
//заголовок пункта меню
Additem. СарИоп:='Добавить тег';
//прозрачный цвет картинки
Add Item. Bitmap.TransparentColor:=cl White;
//признак отображения прозрачного цвета
Add Item. Bitmap.Transparent:=true;
//загрузка картинки из файла
Addltem.Bitmap.LoadFromFile(CurrDir+'\Pictures\Add.bmp');
//создание пункта «Удалить тег» в меню
Del Item:=TMenultem.Create(Self);
//заголовок пункта меню
0е1кет.Сар^оп:='Удалить тег';
//прозрачный цвет картинки
Del Item.Bitmap.TransparentColor:=clWhite;
//признак отображения прозрачного цвета
Del Item.Bitmap.Transparent:=true;
//загрузка картинки из файла
Del Item. Bitmap. Load From File(CurrDir+'\Pictures\Del.bmp');
//добавление пунктов меню в главное меню
//добавление пункта «Добавить тег» в меню
Item. Add(Add Item);
//добавление пункта «Удалить тег» в меню
Item.Add(Delltem);
//создание пункта «ОРС-сервер» в меню
Local :=TMenultem.Create(Self);
//заголовок пункта меню
Local. Caption:='OPC-cepBep';
//прозрачный цвет картинки
Local. Bitmap.TransparentColor:=cl White;
//признак отображения прозрачного цвета
Local. Bitmap.Transparent:=true;
//загрузка картинки из файла
Local. Bitmap. Load From File(CurrDir+'\Pictures\OPC. bmp');
501
РАЗРАБОТКА SCADA-СИСТЕМ
//создание пункта Automation Object в меню
Remote:=TMenultem.Create(Self);
//заголовок пункта меню
Remote.Caption ^'Automation Object';
//прозрачный цвет картинки
Remote. Bitmap.TransparentColor:=cl White;
//признак отображения прозрачного цвета
Remote. Bitmap.Transparent:=true;
//загрузка картинки из файла
Remote. Bitmap. Load From File(CurrDir+'\Pictures\COM. bmp');
//добавление пунктов меню в главное меню
//добавление пункта «ОРС-сервер» в меню
Connect. Add(Local);
//добавление пункта Automation Object в меню
Connect.Add(Remote);
//пункт меню запрещен
Disconnect. Enabled :=false;
//пункт меню запрещен
AddSegment. Enabled :=false;
//пункт меню запрещен
DelSegment.Enabled:=false;
//пункт меню запрещен
AddNode.Enabled:=false;
//пункт меню запрещен
Del Node. Enabled :=false;
//пункт меню запрещен
Add Item. Enabled :=false;
//пункт меню запрещен
Del Item. Enabled: =faIse;
//количество элементов массива Segments
SegmentsCount:=o;
//работа таймера запрещена
Timeri. Enabled :=false;
//интервал таймера
Timeri. Interval :=ю;
//запрет на ввод информации
ItemValue. ReadOnly:=true;
//запрет на ввод информации
ItemQuality. ReadOnly:=true;
//заголовок компонента
GroupBoxi.Caption :='Тад';
//заголовок компонента
502
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
GroupBox2.Caption :='Server';
И заголовок компонента
GroupBox3.Caption:=/Host/;
И заголовок компонента
Item Value. EditLabel. Caption ^'Значение';
И заголовок компонента
ItemQuality. EditLabel. Caption ^'Качество';
//заголовок компонента
HostName. EditLabel. Caption :='Имя';
//текст компонента
HostName.Text:=/ii2-i2/;
//заголовок компонента
HostIP. EditLabel .Caption :='1 Р-адрес';
//текст компонента
HostlP.Text:=/i92.i68.iO2.in/;
//заголовок компонента
OPCServer. EditLabel. Caption :='ОРС';
//текст компонента
OPCServer.Text:='Fastwel.PLCNetOPC';
//заголовок компонента
NServer. EditLabel. Caption ^'Automation Object';
//текст компонента
NServer.Text:='NDgrServer. NDgrSrvr';
//начальное значение переменной
Nt:=false;
//начальное значение переменной
Server:=nil;
//начальное значение переменной
NetServer:=o;
//назначение обработчиков событий
Local. On Cl ick:=Loca I Cl ick;
Remote. OnClick:=RemoteClicl<;
Disconnect. OnCliclc=DisconnectClicl<;
Ext.OnClick:=ExtClicl<;
AddSegment.OnClick:=AddSegmentClicl<;
Add Node.OnCliclc=Add NodeCI ick;
Add Item.OnClick:=AddltemClick;
Save.OnCliclc=SaveClicl<;
Load.OnClick:=LoadClicl<;
DelSegment.0nCliclc=DelSegmentClick;
Del Node.OnClick:=Del NodeCIick;
Del Item.OnCliclc=Del ItemClick;
503
РАЗРАБОТКА SCADA-СИСТЕМ
//полное имя файла
fname:=Dir+'\sys.sy';
// если файл существует
if FileExists(fname)
then
begin
//связь файла с файловой переменной
Assign File(_fzfname);
//открытие файла для чтения
Reset(_f);
//чтение имени ОРС-сервера
readln(_fzs);
//запись имени ОРС-сервера в полеТех1
OPCServer.Text:=s;
//чтение имени Automation Object
readln(_fzs);
//запись имени Automation Object
// в поле Text
N Serve г.Text:=s;
//чтение имени хоста
readln(_f,s);
//запись имени носта в noлeText
HostName.Text:=s;
//чтение IP-адреса мастера
readln(_f,s);
//запись IP-адреса мастера в поле Text
HostlP.Text:=s;
//закрытие файла
CloseFile(_f);
end;
end;
//запуск ОРС-сервера, разрешение и запрещение пунктов
//меню, окон ввода имен серверов, имени и IP-адреса мастера
procedure TMainForm. LocalClick(Sender: TObject);
begin
try
//запуск ОРС-сервера
Server:=CreateComObject
(ProglDToClasslD(OPCServer.Text)) as lOPCServer;
//пункт меню разрешен
Disconnect. Enabled :=true;
504
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
//пункт меню запрещен
Connect. Ena bled: =fa I se;
//компонент запретен
HostName.Enabled:=false;
//компонент запрещен
HostIP. Enabled :=false;
//компонент запрещен
NServer. Enabled :=false;
//компонент запрещен
OPCServer.Enabled:=false;
//начальное значение
SegmentsCount:=o;
//ОРС-клиент взаимодействует с ОРС-сервером
nt:=false;
//пункт меню разрешен
AddSegment. Enabled :=true;
//пункт меню разрешен
DelSegment. Enabled :=true;
//пункт меню разрешен
AddNode.Enabled:=true;
//пункт меню разрешен
Del Node. Enabled :=true;
//пункт меню разрешен
Add Item. Enabled :=true;
//пункт меню разрешен
Del Item. Enabled :=true;
except
//отключение от ОРС-сервера
Server:=nil;
//пункт меню разрешен
Disconnect. Enabled :=false;
//пункт меню запрещен
Connect. Enabled :=true;
//компонент запрещен
HostName.Enabled:=true;
//компонент запрещен
HostlP.Enabled:=true;
//компонент запрещен
NServer. Enabled :=true;
//компонент запрещен
OPCServer.Enabled:=true;
//пункт меню разрешен
505
РАЗРАБОТКА SCADA-СИСТЕМ
AddSegment. Enabled:=false;
//пункт меню разрешен
DelSegment. Enabled :=false;
//пункт меню разрешен
Add Node. Enabled :=false;
//пункт меню разрешен
Del Node. Enabled :=false;
//пункт меню разрешен
Add Item. Enabled :=false;
//пункт меню разрешен
Del Item. Enabled :=false;
end;
end;
//соединение c Automation Object, разрешение и запрещение
//пунктов меню, окон ввода имен серверов, имени и IP-adpeca
//мастера
procedure TMainForm. RemoteClick(Sender: TObject);
var
ffzerror:boolean;
begin
// если Automation Object не запущен
if NetServer=o
then
begin
// имя мастера
SocketConnectioni.Host:=HostName.Text;
//1 P-адрес мастера
SocketConnectioni.Address:=HostlP.Text;
// имя Automation Object на мастере,
//запускает ОРС-сервер и читает с него данные
//название проекта +. + имя интерфейса
SocketConnectioni.ServerName:=NServer.Text;
//соединение с Automation Object
SocketConnectioni.Connected:=true;
//интерфейс для связи с приложением-сервером
NetServer:=SocketConnectioni.AppServer;
//Automation Object невидим
NetServer.Visi ble: =fa Ise;
//ОРС-клиент взаимодействует c Automation Object
nt:=true;
//пункт меню разрешен
506
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Disconnect. Enabled :=true;
//пункт меню запрещен
Connect. Enabled :=false;
//компонент запрещен
HostName. Enabled :=false;
//компонент запрещен
Hostl Р. Ena bled: =fal se;
//компонент запрещен
NServer.Enabled:=false;
//компонент запрещен
OPCServer.Enabled:=false;
//начальное значение
SegmentsCount:=o;
//пункт меню разрешен
AddSegment. Enabled :=true;
//пункт меню запрещен
DelSegment.Enabled:=false;
//пункт меню разрешен
AddNode. Enabled :=true;
//пункт меню запрещен
Del Node. Enabled :=false;
//пункт меню разрешен
Addltem.Enabled:=true;
//пункт меню запрещен
Del Item. Ena bled: =fal se;
end;
// останется false, пока к Automation Object
//обращается другое приложение
ff:=false;
// если ОРС-сервер не запущен на мастере
if not NetServer.ServerExists
then
//пока Automation Object занят другим приложением
while not ff do
//если Automation Object свободен
if NetServer.Server_Enabled
then
begin
// для выхода из цикла
ff:=true;
//пересылка имени ОРС-сервера
//на Automation Object
507
РАЗРАБОТКА SCADA-СИСТЕМ
NetServer.SetServerName(OPCServer.Text);
//считывание ошибки запуска ОРС-сервера
error:=NetServer. Error;
// если произошла ошибка
if error
then
begin
//показ сообщения об ошибке
ShowMessage('He могу запустить сервер!!!7);
//отключение от Automation Object
NetServer:=o;
SocketConnectioni.Connected:=false;
//пункт меню запрещен
AddSegment. Enabled :=false;
//пункт меню запрещен
DelSegment. Enabled :=false;
//пункт меню запрещен
Add Node. Ena bled: =fa I se;
//пункт меню запрещен
DelNode.Enabled:=false;
//пункт меню запрещен
Add Item. Enabled :=false;
//пункт меню запрещен
Del Item. Enabled: =faIse;
//компонент разрешен
HostName. Enabled :=true;
//компонент разрешен
HostIP. Enabled :=true;
//компонент разрешен
NServer. Enabled :=true;
//компонент разрешен
OPCServer. Enabled:=true;
//пункт меню запрещен
Disconnect. Enabled:=false;
//пункт меню разрешен
Connect. Enabled :=true;
//выход из процедуры
Exit;
end;
end;
end;
508
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
//отсоединение от Automation Object, разрешение и
//запрещение пунктов меню, окон ввода имен серверов,
//имени и IP-адреса мастера
procedure TMainForm.DisconnectClick(Sender: TObject);
begin
//отключение от ОРС-сервера
Server:=nil;
//удаление всех сегментов
Segments:=nil;
//отключение от Automation Object
NetServer:=o;
//пункт меню разрешен
Connect. Enabled :=true;
//пункт меню запрещен
Disconnect. Enabled :=false;
//удаление всех узлов
TreeViewl. Items.Clear;
//запрещение работы таймера
Timeri. Enabled :=false;
//начальное значение
SegmentsCount:=o;
//свойство Text компонента
Item Vai ue.Text:=";
//свойство Text компонента
ItemQuality .Text:=";
//пункт меню запрещен
AddSegment. Enabled :=false;
//пункт меню запрещен
DelSegment. Enabled :=false;
//пункт меню запрещен
Add Node. Enabled :=false;
//пункт меню запрещен
Del Node. Ena bled: =fa I se;
//пункт меню запрещен
Additem. Enabled :=false;
//пункт меню запрещен
Del Item.Enabled:=false;
//компонент запрещен
HostName. Enabled :=true;
//компонент запрещен
HostIP. Enabled :=true;
//компонент запрещен
509
РАЗРАБОТКА SCADA-СИСТЕМ
NServer. Enabled :=true;
//компонент запрещен
OPCServer. Enabled :=true;
end;
//добавление сегмента в ОРС-сервер
procedure TMainForm.AddSegmentClick(Sender: TObject);
var
//список существующих сегментов
s:WideString;
//имя сегмента
Seg:string;
//массив имен сегментов
ms:array of string;
ff,fff:boolean;
//счетчики
izj: integer;
begin
//начальное значение
Seg:=";
//вызов диалога для получения имени сегмента
5ед:=иррегСа5е(1пр1ЛВох('Добавление сегмента UltraNet',
'Имя сегмента UltraNet',"));
// если имя не введено
if Seg="
then
//выход из процедуры
exit;
//номер сегмента
i:=GetSegmentlndex(Seg);
// если сегмент уже добавлен
if io-i then
//выход из процедуры
exit;
//если ОРС-клиент взаимодействует с ОРС-сервером
if not nt
then
begin
//увеличение количества сегментов
Inc(SegmentsCount);
//длина динамического массива
SetLength(Segments,SegmentsCount);
//начальное значение
510
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Segments[SegmentsCount-i].Segment:=nil;
//добавление сегмента в ОРС-сервер
ServerAddGroup(Server,Seg,true,5OO,o,
Segments[SegmentsCount-i]. Segment,
Segments[SegmentsCount-i].SegmentHandle);
with Segments[SegmentsCount-i] do
begin
//имя сегмента
SegmentName:=Seg;
//добавлениеузла с именем сегмента
TreeSegment:=TreeViewi. Items. Add(nil,Seg);
//начальное значение
NodesCount:=o;
end
end
//если ОРС-клиент взаимодействует с Automation Object
else
begin
//увеличение количества сегментов
Inc(SegmentsCount);
//длина динамического массива
SetLength(Segments, SegmentsCount);
//false, пока Automation Object занят
ff:=false;
//пока Automation Object занят
while not ff do
//если Automation Object свободен
if NetServer.Server_Enabled
then
begin
// для выхода из цикла
ff:=true;
//считывание списка существующих сегментов
//Ultranet в одной строке через пробел
s:=NetServer.Segments;
end;
//деление списка на отдельные сегменты
//добавление пробела в начало списка
s:=#32+s;
//число элементов в динамическом массиве
j-o;
// если список не пустой
511
РАЗРАБОТКА SCADA-СИСТЕМ
if s<>#32
then
//цикл с i до предпоследнего символа списка
//(последний — пробел)
for i:=1 to Length(s)-i do
//если i-й символ списка не пробел
if s[i]<>#32
then
//к (j-i)-My элементу динамического массива
//добавляется i-й элемент списка
ms[j-i]:=ms[j-i]+s[i]
//если i-u символ списка пробел
else
begin
//увеличение количества элементов
//динамического массива на единицу
lnc(j);
//длина динамического массива
SetLength(msJ);
//начальное значение (]-1)-го элемента
//динамического массива
ms[j-i]:=";
end;
//поиск добавляемого сегмента в списке существующих
//(останется false, если не найдется совпадений в списке)
fff:=false;
//если список был не пустой
if joo
then
//цикл по j-i сегментам
for i:=o toj-i do
//если нашли совпадение
if ms[i]=Seg
then
//true, если есть совпадение
fff:=true;
//длина динамического массива
SetLength(mszo);
//false, пока Automation Object занят
ft: =fa Ise;
// если сегмент не существует
if notfff
512
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
then
//пока Automation Object занят
while not ff do
// если Automation Object свободен
if NetServer.Server_Enabled
then
begin
// для выхода из цикла
ff:=true;
//пересылка на Automation Object имени сегмента
NetServer.SetSegmentName(Seg);
end;
with Segments[SegmentsCount-i] do
begin
// имя сегмента
SegmentName:=Seg;
// добавление узла с именем сегмента
TreeSegment:=TreeViewi. Items. Add(nil,Seg);
//начальное значение
NodesCount:=o;
end;
end;
end;
// добавление узла в ОРС-сервер
procedure TMainForm.AddNodeClick(Sender: TObject);
var
// имя сегмента, узла и тега
Segment, Node, Item ID, Nd : string;
//счетчики
i,j:TOIeEnum;
begin
//начальное значение
Nd:=";
// вызов диалога для получения имени узла
Nd:=UpperCase(lnputBox('Дoбaвлeниe узла','Имя узла',"));
// если имя не введено
if Nd=" then
//выход из процедуры
exit;
//получение имен сегмента и узла
GetNames(Nd,Segment, Node, Item ID);
//номер сегмента
513
РАЗРАБОТКА SCADA-СИСТЕМ
i:=GetSegmentlndex(Segment);
// номер узла
j:=GetNodelndex(Segment,Node);
И если сегмент существует, а узел не существует
if (io-i) and (j=-i)
then
with Segments[i] do
begin
//увеличение количества узла
Inc(NodesCount);
//длина динамического массива
SetLength(Nodes,NodesCount);
//имя узла
Nodes[NodesCount-i].NodeName:=Node;
//начальное значение
Nodes[NodesCount-i].ltemsCount:=o;
// добавление узла с именем узла
Nodes[NodesCount-i].TreeNode:=
TreeViewl. ltems.AddChild(TreeSegmentz Node);
end;
end;
//добавление тега в ОРС-сервер
procedure TMainForm.AddltemClick(Sender: TObject);
var
// имя сегмента, узла и тега
Segment, Node, Item ID:string;
//список имен тегов
s:WideString;
//счетчики
izj,kzlzm:TOIeEnum;
ff,fff,error:boolean;
//массив имен тегов
ms:array of string;
//полное имя тега
ltem:string;
begin
//начальное значение
ltem:=";
//вызов диалога для получения полного имени тега
кет:=иррегСа5е(1пр1ЛВох('Добавление тега'/Имя тега',"));
// если имя не введено
514
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
if ltem="
then
//выход из процедуры
exit;
//если ОРС-клиент взаимодействует с ОРС-сервером
if not nt
then
begin
// если ОРС-сервер запущен и имя тега не пусто
if (Serveronil) and (Length(ltem)oo)
then
begin
//получение имен сегмента, узла и тега
GetNames(ltemzSegmentzNodezltemlD);
//номер сегмента
i:=GetSegmentlndex(Segment);
// номер узла
j:=GetNodelndex(Segment,Node);
//номер тега
lc=Getltemlndex(Segmentz Node, Item ID);
// если сегмент и узел существуют,
Ца тег не существует
if (io-i) and (jo-i) and (k=-i)
then
with Segments[i].Nodes[j] do
begin
//увеличение количества тегов
Inc(ltemsCount);
//длина динамического массива
SetLength(ltemszltemsCount);
//добавление тега в ОРС-сервер
HR:=GroupAddltem(Segments[i].Segment,Segment+7+
Node+7+ ltemlDzSegments[i].SegmentHandlezVT_EMPTYz
ltems[ltemsCount-i]. Item Handle, ltems[ltemsCount-i].ltemType);
// если тег добавлен успешно
if Succeeded(HR)
then
begin
// имя тега
ltems[ltemsCount-i].ltemName:=ltemlD;
// добавление узла с именем тега
ltems[ltemsCount-i]. Treeitem :=
515
РАЗРАБОТКА SCADA-СИСТЕМ
TreeViewl. Items. AddChild(TreeNodez Item ID);
end
//ес/ш тег не добавлен
else
begin
//уменьшение количества тегов
Dec(ltemsCount);
//длина динамического массива
SetLength(ltemszltemsCount);
end;
end;
end;
end
// если ОРС-клиент взаимодействует с Automation Object
else
begin
//получение имен сегмента, узла и тега
GetNames(ltemzSegmentzNodezltemlD);
//номер сегмента
i:=GetSegmentlndex(Segment);
//номер узла
j:=GetNodelndex(SegmentzNode);
//номер тега
lc=Getltemlndex(Segmentz Node, Item ID);
// если сегмент и узел существуют, а тег не существует
if (io-i) and (jo-i) and (k=-i)
then
with Segments[i].Nodes[j] do
begin
//увеличение количества тегов
Inc(ltemsCount);
//длина динамического массива
SetLength(ltemszltemsCount);
//false, пока сервер занят
ff:=false;
//пока сервер занят
while not ff do
// если сервер свободен
if NetServer.Server_Enabled
then
begin
// для выхода из цикла
516
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
ff:=true;
//считывание списка имен тегов
// в одной строке через пробел
s:=NetServer. Items;
end;
//деление списка на отдельные имена тегов
//добавление пробела в начало списка
s:=#32+s;
//количество элементов в динамическом массиве
I :=0;
//длина динамического массива
SetLength(mszl);
// если список не пуст
if s<>#32
then
//цикл с i-го символа до предпоследнего
for m:=i to Length(s)-i do
// если т-й символ строки не пробел
if s[m]<>#32
then
//добавление к (1-1)-му элементу динамического
//массива т-го символа списка
ms[l-i] :=ms[l-i]+s[m]
//если т-й символ пробел
else
begin
//количество элементов динамического массива
1пс(1);
//длина динамического массива
SetLength(mszl);
//начальное значение
ms[l-i]:=";
end;
//поиск совпадений добавляемого тега с уже
//существующими (останется false, если не найдется
//совпадений добавляемого тега с уже существующими)
fff:=false;
// если длина динамического массива не равна нулю
if Length(ms)oo
then
//цикл по количеству элементов динамического массива
for m:=o to Length(ms)-i do
517
РАЗРАБОТКА SCADA-СИСТЕМ
//если нашелся такой же тег в списке
if ms[m]=ltem
then
begin
Ц true, если добавляемый тег уже добавлен
fff:=true;
//номер тега в списке
ltems[ltemsCount-i].Number:=m;
end;
//длина динамического массива
SetLength(mszo);
//начальное значение
error:=false;
//если добавляемого тега нет в списке
if notfff
then
begin
//false, пока сервер занят
ft: =f a Ise;
//пока сервер занят
while not ff do
// если сервер свободен
if NetServer.Server_Enabled
then
begin
// для выхода из цикла
ff:=true;
//добавление имени тега на Automation Object
NetServer.SetltemName(ltemzSegment);
//считывание ошибки
error:=NetServer. Error;
end;
//false, пока сервер занят
ft: =f a Ise;
//пока сервер занят
while not ff do
// если сервер свободен
if NetServer.Server_Enabled
then
begin
// для выхода из цикла
ff:=true;
518
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
//список имен тегов в одной строке через пробел
s:=NetServer. Items;
end;
//добавление пробела в начало списка
s:=#32+s;
//количество элементов в динамическом массиве
1:=0;
//длина динамического массива
SetLength(mszl);
// если список не пуст
if s<>#32 then
//цикл с i-го по предпоследний символ списка
for m:=i to Length(s)-i do
// если т-й символ не пробел
if s[m]<>#32
then
//добавление к (1-1)-му элементу т-го символ списка
ms[l-i]:=ms[l-i]+s[m]
//если т-й символ — пробел
else
begin
//увеличение количества
1пс(1);
//длина динамического массива
SetLength(mszl);
//начальное значение
ms[l-i]:=";
end;
// если длина динамического массива не равна нулю
if Length(ms)oo
then
//цикл по количеству элементов динамического массива
for m:=o to Length(ms)-i do
//если нашли в списке добавленный тег
if ms[m]=ltem
then
//порядковый номер тега в списке
ltems[ltemsCount-i].Number:=m;
//длина динамического массива
SetLength(mszo);
end;
// если при добавлении тега не произошло ошибки
519
РАЗРАБОТКА SCADA-СИСТЕМ
if not error
then
begin
// имя тега
ltems[ltemsCount-i].ltemName:=ltemlD;
// добавление узла с именем тега
ltems[ltemsCount-i]. Treeitem :=
TreeViewl. Items. AddChild(TreeNode, Item ID);
end
Несли при добавлении тега произошла ошибка
else
begin
//уменьшение количества тегов
Dec(ltemsCount);
//длина динамического массива
SetLength(ltemszltemsCount);
end;
end;
end;
end;
//удаление сегмента из ОРС-сервера, сдвиг всех элементов
//массива segments на один влево (к началу массива)
// после удаляемого и удаление последнего элемента
procedure TMainForm. DelSegmentClick(Sender: TObject);
var
// имя сегмента
Seg:string;
//счетчики и номер сегмента
ijXn-Segmentinteger;
begin
//начальное значение
Seg:=";
//имя сегмента
5ед:=иррегСа5е(1пр1ЛВох('Удаление сегмента UltraNet,
'Имя сегмента UltraNet,"));
//имя сегмента не пусто
if Sego"
then
begin
//запрещение работы таймера
Timeri. Enabled :=false;
520
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
//начальное значение
ItemValue.Text:^";
//начальное значение
ltemQuality.Text:=";
//номер сегмента
n_Segment:=GetSegmentlndex(Seg);
// если номер сегмента не равен минус единице
if n_Segmento-i
then
begin
// если количество узлов не равно нулю
if Segments[n_Segment].NodesCountoo
then
//цикл по количеству узлов
for j:=о to Segments[n_Segment].NodesCount-i do
//если количество тегов не равно нулю
if Segments[n_Segment].Nodes[j].ltemsCountoo
then
//цикл по количеству тегов
for k:=о to Segments[n_Segment].Nodes[j].
ItemsCount-i do
//удаление тега из ОРС-сервера
HR:=GroupRemoveltem(Segments[n_Segment]. Segment,
Segments[n_Segment].Nodes[j].ltems[k].
ItemHandle);
//удаление сегмента из ОРС-сервера
Server. RemoveGroup(Segments[n_Segment].
SegmentHandle, false);
//удаление узла с именем сегмента
TreeViewl. Items. Delete(Segments[n_Segment].
TreeSegment);
// если номер сегмента не равен номеру последнего сегмента
if n_Segment<>SegmentsCount-i
then
//цикл по всем сегментам после удаленного
for i:=n_Segment to SegmentsCount-2 do
begin
// имя сегмента
Segments[i].SegmentName:=Segments[i+i].
SegmentName;
//интерфейс для добавления или удаления сегментов
Segments[i].Segment:=Segments[i+i]. Segment;
521
РАЗРАБОТКА SCADA-СИСТЕМ
И хэндл сегмента
Segments[i].SegmentHandle:=Segments[i+i].
SegmentHandle;
И узел в KOMnoHenmeTreeViewi
Segments[i].TreeSegment:=Segments[i+i].
TreeSegment;
// количество узлов
Segments[i].NodesCount:=Segments[i+i].
NodesCount;
//длина динамического массива
SetLength(Segments[i].NodeszSegments[i].
NodesCount);
// если количество узлов не равно нулю
if Segments[i].NodesCountoo
then
//цикл по количеству узлов
for j:=о to Segments[i].NodesCount-i do
begin
// имя узла
Segments[i].Nodes[j].NodeName:=
Segments[i+i].Nodes[j].NodeName;
//количество тегов
Segments[i].Nodes[j].ltemsCount:=
Segments[i+i].Nodes[j].ltemsCount;
//узел в компоненте TreeViewl
Segments[i].Nodes[j].TreeNode:=
Segments[i+i].Nodes[j].TreeNode;
//длина динамического массива
SetLength(Segments[i].Nodes[j]. Items,
Segments[i].Nodes[j].ltemsCount);
// если число тегов не равно нулю
if Segments[i].Nodes[j].ltemsCountoothen
//цикл по количеству тегов
for к:=о to Segments[i].Nodes[j].ltemsCount-i do
begin
//имя сегмента
Segments[i].Nodes[j].ltems[k].ltemName:=
Segments[i+i].Nodes[j].ltems[k]. Item Name;
//хэндл тега
Segments[i].Nodes[j].ltems[l<].Item Handler
Segments[i+i].Nodes[j].ltems[k]. Item Handle;
//узел в KOMnoHenmeTreeViewi
522
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Segments[i].Nodes[j].ltems[k].Treeltem:=
Segments[i+i].Nodes[j].ltems[k].Treeitem;
//тип тега
Segments[i].Nodes[j].ltems[k].ltemType:=
Segments[i+i].Nodes[j].ltems[k].ltemType;
end;
end;
end;
//количество сегментов
SegmentsCount:=SegmentsCount-i;
//длина динамического массива
SetLength(SegmentszSegmentsCount);
end;
end;
end;
//удаление узла, сдвиг всех элементов массива
//nodes на один влево (к началу массива) после удаляемого
И и удаление последнего элемента
procedure TMainForm. DelNodeClick(Sender: TObject);
var
//имя сегмента, узла и тега
Nd/Segment/Node/item:string;
//счетчики, номер сегмента и узла
j/kzn_Segmentzn_Node:integer;
begin
//начальное значение
Nd:=";
// имя узла
Ш:=иррегСа5е(1при1Вох('Удаление узла'/Имя узла'/'));
// если имя узла не пусто
if Ndo" then
begin
//запрещение работы таймера
Timen. Enabled :=false;
//начальное значение
ltemValue.Text:=";
//начальное значение
ltemQuality.Text:=";
//получение имен сегмента и узла по полному имени узла
GetNames(NdzSegmentzNodezitem);
//номер сегмента
523
РАЗРАБОТКА SCADA-СИСТЕМ
n_Segment:=GetSegmentlndex(Segment);
// номер узла
n_Node:=GetNodelndex(Segment,Node);
И если сегмет и узел существуют
if (n_Segmento-i) and (n_Nodeo-i) then
begin
// если число тегов не равно нулю
if Segments[n_Segment].Nodes[n_Node].
ItemsCountoo
then
//цикл no количеству тегов
for j:=о to Segments[n_Segment].Nodes[n_Node].
ItemsCount-i do
//удаление тега из ОРС-сервера
HR:=GroupRemoveltem(Segments[n_Segment].
Segment, Segments[n_Segment].Nodes[n_Node].
Items[j]. Item Handle);
//удаление узла с именем узла
TreeViewl. Items. Delete
(Segments[n_Segment].Nodes[n_Node].TreeNode);
// если узел не последний в массиве
if n_Node<>Segments[n_Segment].NodesCount-i
then
//цикл по узлам после удаляемого
for j:=n_Node to Segments[n_Segment].NodesCount-2 do
begin
// имя узла
Segments[n_Segment].Nodes[j].NodeName:=
Segments[n_Segment].Nodes[j+i].NodeName;
//количество тегов
Segments[n_Segment].Nodes[j].ltemsCount:=
Segments[n_Segment].Nodes[j+i].ltemsCount;
//узел в KOMnoHenmeTreeViewi
Segments[n_Segment].Nodes[j].TreeNode:=
Segments[n_Segment].Nodes[j+i].TreeNode;
//длина динамического массива
SetLength(Segments[n_Segment].Nodes[j]. Items,
Segments[n_Segment].Nodes[j].ltemsCount);
// если количество тегов не равно нулю
if Segments[n_Segment].Nodes[j]. ItemsCountoo
then
//цикл no количеству тегов
524
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
for lc=oto Segments[n_Segment].Nodes[j].
ItemsCount-i do
begin
// имя тега
Segments[n_Segment].Nodes[j].ltems[k].
ltemName:= Segments[n_Segment].Nodes[j+i].
Items[k]. ItemName;
//хэндл тега
Segments[n_Segment].Nodes[j].ltems[k].
ltemHandle:= Segments[n_Segment].Nodes[j+i].
Items[k]. Item Handle;
//узел в компоненте TreeViewl
Segments[n_Segment].Nodes[j].ltems[k].
Treeitem := Segments[n_Segment].Nodes[j+i].
ltems[k].Treeltem;
//тип тега
Segments[n_Segment].Nodes[j].ltems[k].
ltemType:= Segments[n_Segment].
Nodes[j+i].ltems[k]. ItemType;
end;
end;
// количество узлов
Segments[n_Segment].NodesCount:=
Segments[n_Segment].NodesCount-i;
//длина динамического массива
SetLength(Segments[n_Segment]. Nodes,
Segments[n_Segment].NodesCount);
end;
end;
end;
//удаление тега из ОРС-сервера, сдвиг всех элементов
И массива items на один влево (к началу массива)
И после удаляемого и удаление последнего элемента
procedure TMainForm. DelltemClick(Sender: TObject);
var
//имя сегмента, узла и тега
Itm,Segment, Node, item :string;
//счетчик, номер сегмента, узла и тега
k, n_Segment,n_Node,n_item integer;
begin
//начальное значение
525
РАЗРАБОТКА SCADA-СИСТЕМ
Itm
//шин тега
Нт:=иррегСа5е(1при1Вох('Удаление тега '/Имя тега',"));
И если имя тега не пусто
if Itmo"
then
begin
//запрещение работы таймера
Timeri. Enabled :=false;
//начальное значение
ltemValue.Text:=";
//начальное значение
ItemQuality .Text:=";
//получение имен сегмента, узла и тега
GetNames(ltm,Segment, Node, item);
//номер сегмента
n_Segment:=GetSegmentlndex(Segment);
// номер узла
n_Node:=GetNodelndex(Segment,Node);
//номер тега
n_item:=Getltemlndex(Segmentz Node, item);
//если сегмент, узел и тег существуют
if (n_Segmento-i) and (n_Nodeo-i) and (n_itemo-i)
then
with Segments[n_Segment].Nodes[n_Node] do
begin
//удаление узла с именем тега
TreeViewl. Items. Delete(ltems[n_item]. Treeitem);
//удаление тега из ОРС-сервера
HR:=GroupRemoveltem(Segments[n_Segment].
Segment, ltems[n_item]. Item Handle);
// если удаляемый тег не последний в массиве
if n_itemoltemsCount-i
then
//цикл по тегам после удаляемого
for lc=n_item to ltemsCount-2 do
begin
// имя тега
ltems[k]. Item Name:=ltems[k+i], Item Name;
//хэндл тега
Itemsfk], Item Handle:=ltems[k+i], Item Handle;
//узел в KOMnoHenmeTreeViewi
526
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Items[l<].Treeitem :=ltems[k+i].Treeitem;
//тип тега
ltems[k].ltemType:=ltems[k+i]. ItemType;
end;
//количество тегов
ltemsCount:=ltemsCount-i;
//длина динамического массива
SetLength(ltemszltemsCount);
end;
end;
end;
//поиск в массивах Segments, Nodes и Items выделенного
//пользователем тега и сохранение номеров сегмента,
И узла и тега в соответствующие переменные
procedure TMainForm.TreeViewiClick(Sender: TObject);
var
//счетчики
izjzk:TOIeEnum;
begin
//свойство Text компонента
Item Vai ue.Text:=";
//свойство Text компонента
ItemQuality .Text:=";
//запрещение работы таймера
Timeri. Enabled :=false;
// если количество сегментов не равно нулю
if SegmentsCountoo
then
//цикл по всем сегментам
for i:=о to SegmentsCount-i do
// если количество узлов не равно нулю
if Segments[i].NodesCountoo
then
//цикл по всем узлам
for j:=о to Segments[i].NodesCount-i do
// если количество тегов не равно нулю
if Segments[i].Nodes[j]. ItemsCountoo
then
//цикл no всем тегам
for k:=o to Segments[i].Nodes[j].ltemsCount-i do
// если k-й тег выделен пользователем
527
РАЗРАБОТКА SCADA-СИСТЕМ
if Segments[i].Nodes[j].ltems[k].Treeltem.Selected
then
begin
//номер сегмента
SegmentNumber:=i;
// номер узла
NodeNumber:=j;
//номер тега
ltemNumber:=l<;
//разрешение работы таймера
Timen. Enabled :=true;
//выход из процедуры
exit;
end;
end;
//чтение значений тегов из ОРС-сервера или Automation Object
procedure TMainForm J"imeriTimer(Sender: TObject);
var
//счетчики
i,j:integer;
//массив строк, служит для обмена данными между
//клиентом и Automation Object
ms:array of string;
//список тегов, получаемый от Automation Object
Itms: WideString;
begin
//значения SegmentNumber, NodeNumber и ItemNumber
//вычисляются при выборе тега на KOMnoHenmeTreeViewi
with Segments[SegmentNumber].Nodes[NodeNumber] do
// если ОРС-клиент взаимодействует ОРС-сервером
if not nt
then
begin
//чтение значения выбранного тега
HR:=ReadOPCGroupltemValue(Segments[SegmentNumber].
Segment, Items [Item Number]. Item Handle, ltems[ltem Number].
Item Value, ltems[ltem Number]. ItemQuality);
// если результат успешен
if Succeeded(HR)
then
begin
528
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
//если тип выбранного тега Real
if GetltemType(ltems[ltem Number]. Item Value)=Tloat/
then
//запись значения тега в поле Text
ltemValue.Text:=
FloatToStrF(StrToFloat(ltems[ltem Number].
Item Vai ue)/fffixed/i5/7)
// в любом другом случае
else
//запись значения тега в поле Text
Item Vai ue.Text:=ltems[ltem Number]. Item Value;
// если качество связи тега хорошее
if (ltems[ltem Number]. ItemQuality and
OPC_QUALITY_MASK) = OPC_QUALITY_GOOD
then
ItemQuality .Text:='Good'
//если качество связи плохое
else
ItemQuality .Text:='Bad';
end;
end
//если ОРС-клиент взаимодействует c Automation Object
else
begin
//считывание значений тегов в одной строке через пробел
ltms:=NetServer.ltms;
//добавление пробела в начало списка
ltms:=#32+ltms;
//количество элементов динамического массива
j-o;
//если список не пуст
if ltms<>#32
then
//цикл по количеству элементов динамического массива
for i:=i to Length(ltms)-i do
//если i-й символ списка не пробел
if ltms[i]<>#32
then
//добавление к (j-i)-My элементу i-го символа списка о сервер
ServerAddGroup(ServerzOPCServer.Textz
truez5OOzozSegmentzSegmentHandle);
// добавление узла с именем сегмента
529
РАЗРАБОТКА SCADA-СИСТЕМ
TreeSegment:=TreeViewi. Items. Add First(nil,
SegmentName);
//чтение количества узла
Readln(f,NodesCount);
//длина динамического массива
SetLength(Nodes,NodesCount);
// если число узлов не равно нулю
if NodesCountoo
then
//цикл по количеству узлов
for j:=о to NodesCount-i do
begin
//чтение имени узла
Readln(f,Nodes[j].NodeName);
//добавление имени узла с именем узла
Nodes[j].TreeNode:=
TreeViewl. ltems.AddChild(TreeSegmentz
Nodes[j].NodeName);
//чтение количества тегов
Readln(f,Nodes[j].ltemsCount);
//длина динамического массива
SetLength(Nodes[j]. Items, Nodes[j].ltemsCount);
//если количество тегов не равно нулю
if Nodes[j]. ItemsCountoo
then
//цикл no количеству тегов
for к:=о to Nodes[j].ltemsCount-i do
begin
//чтение имени тега
Readln(f,Nodes[j].ltems[k]. Item Name);
//добавление тега в ОРС-сервер
GroupAddltem(Segment,SegmentName+'.'+
Nodes[j].NodeName+7+Nodes[j].ltems[k].
ItemName, SegmentHandlezVT_EMPTY,
Nodes[j].ltems[k].Item Handle,Nodes[j].
Items[k].ItemType);
//добавлениеузла с именем тега
Nodes[j].ltems[k] .Treeitem :=
TreeViewl. Items. AddChild
(Nodes[j].TreeNode,Nodes[j].
Items[k]. Item Name);
end;
530
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
end;
end;
//закрытие файла
CloseFile(f);
//пункт меню разрешен
AddSegment. Enabled :=true;
//пункт меню разрешен
DelSegment. Enabled :=true;
//пункт меню разрешен
AddNode.Enabled:=true;
//пункт меню разрешен
Del Node. Enabled :=true;
//пункт меню разрешен
Addltem.Enabled:=true;
//пункт меню разрешен
Del Item. Ena bled: =true;
end;
end;
//действия, вызванные щелчком на пункте «Выход» меню
procedure TMainForm. ExtClick(Sender: TObject);
begin
//отключение от ОРС-сервера
Server:=nil;
//отключение от Automation Object
NetServer:=o;
//завершение работы приложения
Application.Terminate;
end;
//действия при закрытии формы
procedure TMainForm. FormClose(Sender: TObject; var
Action: TCIoseAction);
var
//файловая переменная
f:textFile;
//полное имя файла sys.sy
fn a me: string;
begin
//уничтожение главного меню
MainMenu:=nil;
//отключение от Automation Object
531
РАЗРАБОТКА SCADA-СИСТЕМ
NetServer:=o;
//уничтожение массива Segments
Segments:=nil;
//отключение от ОРС-сервера
Server:=nil;
//полное имя файла
fname:=Dir+'\sys.sy';
// связь файловой переменной с файлом
AssignFile(fzfname);
//открытие файла для записи
Rewrite(f);
//запись имени ОРС-сервера
writeln(fzOPCServer.text);
//запись имени Automation Object
writeln(fzNServer.text);
//запись имени мастера
writeln(fz HostName. text);
//запись IP-адреса мастера
writeln(fzHostlP.text);
//закрытие файла
CloseFile(f);
end;
end.
3.3.4. Работа с ОРС-клиентом
Внешний вид ОРС-клиента, его каталог и файлы
На рис. 3.71 изображена форма ОРС-клиента на этапе разра-
ботки в среде визуального проектирования Delphi 7. На рис. 3.72
показан каталог проекта ОРС-клиента со всеми файлами (файлы
проекта, файлы подключаемых модулей, файлы хранения конфигу-
рации ОРС-клиента) и каталог Pictures, содержащий файлы изобра-
жений для ряда кнопок проекта.
532
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Рис. 3.71. Форма ОРС-клиента в среде
Delphi 7
IM ОРС Client
Файл Правка Вид Избр >>
Назад -
Адрес: | } ОРС Client kJ Переход
jPictures
jJ config, sav
Si] Main.~ddp
21 Main.~dfm
3Si| Main.-pas
SliMain.dcu
231 Main.ddp
^Main.dfm
jf ’ Main.pas
£ OPC_AE.pas
22? OPCjZlient.~dpr
OPCjClient.cfg
^OPCjCIient.dof
>OPC_Client.dpr
“yoPC_Client.exe
SjOPC.CIient.res
if-OPCCOMN.pas
OPCDA.—pas
SjOPCDA.dcu
if' OPCDA.pas
jf OPCerror.pas
if' OPCHDA.pas
# OPCSEC.pas
SlJOPCtypes.dcu
if-OPCtypes.pas
Sl| OPC util s. -pas
SjOPCUtils.dcu
T OPCutils.pas
Й sys.sy
Объектов: 29 931 КБ
| Мой ко
Рис. 3.72. Каталог проекта
ОРС-клиента
На рис. 3.73 показан каталог Pictures, содержащий файлы изо-
бражений для подпунктов главного меню. На рис. 3.74 показан при-
мер файла конфигурации, сохраняемого пользователем, причем имя
и местоположение файла выбирается пользователем. Файлов кон-
фигурации может быть несколько.
25Add.bmp
Зсом.ьтр
Del.bmp
Exit.bmp
SOPGbmp
.3 Open.bmp
*4 Options.bmp
2>Save.bmp
25 Start.bmp
S Stop.bmp
В config.sav - Блокнот
Файл Правка Формат Вид Справка
i 3
ULTRANET-1
1
FE
5
VX0D1
VX0D2
VX0D3
VX0D4
VX0D6
3
Рис. 3.74. Пример файла конфигурации
пользователя
Рис. 3.73. Каталог Pictures
533
РАЗРАБОТКА SCADA-СИСТЕМ
Общая структура файла конфигурации:
- количество сегментов сети Ultranet;
- структура сегмента Segment 1, которая содержит:
• имя сегмента Segment 1;
• количество узлов в сегменте Segmentl;
• структуру узла Node 1, которая содержит:
° имя узла Node 1;
° количество тегов в узле Node 1;
° имя тега Tag 1;
° имя тега Tag2;
° имя тега TagK;
• структуру узла Node2;
• структуру узла NodeM;
- структура сегмента Segment2;
- структура сегмента SegmentN.
В нашем случае имеется один сегмент сети ULTRANET_1,
содержащий один узел FE, который содержит пять тегов: VXOD1,
VXOD2, VXOD3, VXOD4 и VXOD6.
На рис. 3.75 показан файл конфигурации sys.sy, который сохра-
няется ОРС-клиентом после закрытия. Структура файла sys.sy:
- имя ОРС-сервера;
- имя объекта автоматизации и имя интерфейса, разделенные
точкой;
- имя удаленного мастера сети;
- IP-адрес мастера.
На рис. 3.76 показано окно ОРС-клиента после запуска.
534
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
| У ОРС-кпиент
Файл Сегмент UltraNet Узел Тег
Р sys.sy - Блокнот
Файл Правка Формат Вид Справка
Fastwel.PLCNetOPC 2
NDgrServer.NDgrSrvr
112-12
192.168.102.111
Тад
Значение
I-------------------
Качество
I
-Servei----
ОРС_________________
| Fastwel.PLCNetOPC
Automation Object
(NDgrServei.NDgrSrvr
Host
Имя
|l 12-12
IP-адрес
1192.163.102.111
Рис. 3.75. Файл конфигурации
sys-sy
Рис. 3.76. Окно ОРС-клиента
после запуска
Пункт меню «Файл» (рис. 3.77) содержит пункты подменю:
- «Открыть» — открывает файл конфигурации;
- «Сохранить» — сохраняет файл конфигурации;
- «Пуск» — содержит (рис. 3.78) подпункты:
«ОРС-сервер» — подключение к ОРС-серверу;
Automation Object— подключение к О А.
й
ОРС-клиент
Файл Сегмент UltraNet Узел Тег
_/* Открыть... --------------------
>, Сохранить...
► Пуск ►
® ' топ
JCL Выход...
Файл Сегмент UltraNet Узел Тег
Открыть...
J Сохранить...
S Сто
XL Выход...
i Automation Object
Тад
Чнаиение
Seiver
OPC_________________
(Fastwel. PLCNetOPC
Automation Object
| NDgrSetver.ND grSrvr
Host
Имя
(112-12
IP-адрес
(192.168.102.111
Б
Рис. 3.77. Меню «Файл»
Рис. 3.78. Меню «Пуск»
535
РАЗРАБОТКА SCADA-СИСТЕМ
Пункт меню «Сегмент UltraNet» рис. 3.79 содержит подпун-
кты:
- «Добавить сегмент UltraNet» — добавляет новый сегмент
в сеть;
- «Удалить сегмент UltraNet» — удаляет выбранный сег-
мент сети.
Пункт меню «Узел» рис. 3.80 содержит подпункты:
- «Добавить узел» — добавление нового узла;
- «Удалить узел» — удаление выбранного узла.
Файл Сегмент UltraNet Узел Тег
Добавить узел
X Удалить узел
Рис. 3.79. Меню «Сегмент UltraNet»
^ние
Качество
Server
ОРС-клиент
ОРС_____________
| Fast wel.PLCN elO PC
Automation Object
|NDgrServer.NDgrSrvr
Host
Имя
jl12-12~
IP-адрес
|192.1S8.1O2.111
Рис. 3.80. Меню «Узел»
Пункт меню «Тег» рис. 3.81 содержит подпункты:
- «Добавить тег» — добавление нового тега;
- «Удалить тег» — удаление выбранного тега.
536
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
ОРС-клиент
Файл Сегмент UltraNet Узел Тег
Добавить тег
X Удалить тег
т=
Качество
I_________
Server
ОРС_______________
| FastweLPLCNetOPC
Automation Object
[NDgrServer.NDgrSrvr
Host
Имя
[гЁМ2
IP-адрес
|192.168.1O2.111
Рис. 3.81. Меню «Тег»
Подключение, добавление и удаление сегментов сети,
узлов и тегов, сохранение и загрузка файла конфигурации
Подключение ОРС-клиента к ОРС-серверу показано на рис. 3.82.
Подключение ОРС-клиента к ОА показано на рис. 3.83.
Файл Сегмент UltraNet Узел Тег
_> Открыть...
jj Сохранить...
Пуск
Q Стоп
JTL Выход...
-i. Automation Object
I----------------— качество
Server
ОРС
[FastweLPLCNetOPC
Automation Object
[NDgrServer.NDgrSrvr
| jr'ОРС-клиент
Файл Сегмент UltraNet Узел Тег
__‘ Открыть...
Л Сохранить..
Automation Object
[ Tag---
Учение
1 ОРС-сервер
Е
Пуск
О Стол
JTL Выход...
ство
Server
OPC
[FastweLPLCNetOPC
Automation Object
[NDgrServer.NDgrSrvr
Host
Имя
|l 12-12
IP-адрес
|l 92.168.102.111
Host
Имя
|112-12
IP-адрес
[192.168.102.111
Рис. 3.82. Подключение ОРС-клиента
кОРС-серверу
Рис. 3.83. Подключение ОРС-клиента
кОА
537
РАЗРАБОТКА SCADA-СИСТЕМ
Добавление сегмента сети UltraNet к сети показано на рис. 3.84.
Здесь ввод полного имени сегмента сети показан на рис. 3.85, а до-
бавление имени сегмента в дерево объектов ОРС-клиента приведе-
но на рис. 3.86.
Добавление узла показано на рис. 3.87. Ввод полного имени
узла показан на рис. 3.88. Добавление имени узла в дерево объектов
ОРС-клиента показано на рис. 3.89.
UPC-клиент
Файл , Сегмент UltraNet Узел Тег
Рис. 3.84. Добавление сегмента сети
U It га Net
E
Файл Сегмент UltraNet Узел Тег
Tag -----
Значение
Качество
Добавление сегмента UltraNet
Имя сегмента UltraNet
|UHranet_1
ОК | Cancel |
Host
Имя
f 12-12
IP-адрес
|192 168.102111
Рис. 3.85. Ввод полного имени
сегмента сети
Файл Сегмент UltraNet Узел Тег
[ULTRANETJ
^1 : х
Файл Сегмент UltraNet Узел Тег
U'
Добавить узел
X Удалить узел
Качество
Server
ОРС
(fastwel PLCNetOPL
Automation Object
(rlDgrSe
Host
Имя
|-12-12
IP-адрес
|'У2.1Ь8 102111
Рис. 3.86. Добавление имени сегмента
в дерево объектов ОРС-клиента
538
Рис. 3.87. Добавление узла
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Файл Сегмент UltraNet Узел Тег
'□РС-кяиенп
Файл сегмент UltraNet Узел Тег
Рис. 3.88. Ввод полного имени узла
- ULTRANETJ Тад
S3 Значение
I
Качество
I------------------
Servei
□PC
|Fastwel.PLCNetOPC
Automation Obiect
Host
Имя
|l 12-12
IP-адрес
|l 92168.102111
Рис. 3.89. Добавление имени узла
в дерево объектов ОРС-клиента
Добавление тега показано на рис. 3.90. Ввод полного имени
тега показан на рис. 3.91. Добавление имени тега в дерево объек-
тов ОРС-клиента показано на рис. 3.92. Удаление тега показано
на рис. 3.93.
Файл Сегмент UltraNet Узел Тег
- ULTRANETJ
S3
X Удалить тег
Добавить тег
Качество
Seiver
ОРС
jFastwel PLCNelOPC
Файл сегмент UltraNet Узел Тег
Automation Object
|NDgiS<
Host
Имя
|112-12
IP-адрес
|192.168 102.111
Рис. 3.91. Ввод полного имени тега
Рис. 3.90. Добавление тега
539
РАЗРАБОТКА SCADA-СИСТЕМ
Рис. 3.92. Добавление имени тега
в дерево объектов ОРС-клиента
ОРС-клиент
Файл Сегмент UltraNet Узел Тег
- ULTRANET 1
О FE
VX0D2
FD
J0.2882516
Качество
[Good
-Server
-=JZj2£j
ОРС
[FastweLPLCNetOPC
Automation Object
rS eiver.NDgrS
Host-
Имя
|11 -
IP-адрес
[192.168.102.111
РИС. 3.93. Удаление тега
Ввод полного имени тега при удалении показан на рис. 3.94.
объектов ОРС-клиента показано
Удаление имени тега из дерева
на рис. 3.95.
|7 * ОРС-клиент
Файл Сегмент UltraNet Узел Тег
В ULTRANET.1
- FE
VX0D1
VX0D2
FD
Тад-
Значение
|0.2886832
Качество
Good
Файл Сегмент UltraNet Узел Тег
- ULTRANETJ
- FE
FD
Имя тега
]Ultranet_1.FE.Vxod2
| OK | Cancel |
Е rvr
Host
Имя
|'| 12-12
1Р-адоес
[192168.102111
Рис. 3.94. Ввод полного имени тега
при удалении
Рис. 3.95. Удаление имени тега
из дерева объектов ОРС-клиента
540
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Удаление узла из ОРС-клиента показано на рис. 3.96. Ввод пол-
ного имени узла при удалении показан на рис. 3.97.
Рис. 3.96. Удаление узла
из ОРС-клиента
Рис. 3.97. Ввод полного имени узла
при удалении
Удаление имени узла из дерева объектов ОРС-клиента показано
на рис. 3.98. Удаление сегмента сети UltraNet показано на рис. 3.99.
Файл Сегмент UltraNet Узел Тег
- ULTRANETJ
В FE
Servei —
пре
Automation Object
|flDgrServer NDgiSivr
Host
Г-
IP-адрес
|l S2168.102.111
Рис. 3.98. Удаление имени узла из
дерева объектов ОРС-клиента
Рис. 3.99. Удаление сегмента сети
UltraNet
541
РАЗРАБОТКА SCADA-СИСТЕМ
Ввод полного имени сегмента при его удалении показан на
рис. 3.100. Удаление имени сегмента из дерева объектов ОРС-
из дерева объектов ОРС-клиента
сегмента при его удалении
Отключение ОРС-клиента от ОРС-сервера или ОА показано на
рис. 3.102. После отключения становятся доступными окна ввода
имен ОРС-сервера, ОА, а также IP-адреса и имени мастера рис. 3.103.
Рис. 3.102. Отключение ОРС-клиента
от ОРС-сервера или ОА
Рис. 3.103. Вид окна после отключения
ОРС-клиента от ОРС-сервера или ОА
542
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Загрузка файла конфигурации приведена на рис. 3.104. Выбор
файла показан на рис. 3.105.
|jrr ОРС-клиент
Файл Сегмент UltraNet Узел Тег
й Сохранить...
► Пуск
О Стоп
Д Выход...
Рис. 3.104. Загрузка файла конфигурации
Открыть
Папка: [" ОРС Client
_ Pictures
Имя Файла: | config, soy
Т ип Файлов: | Файлы (“.sav)
Открыть |
Отмена |
Рис. 3.105. Выбор файла конфигурации
После загрузки происходит подключение ОРС-клиента к ОРС-
серверу (для ОА функция не реализована) и восстановление де-
рева объектов (рис. 3.106). Добавление нового тега показано на
рис. 3.107. Сохранение файла конфигурации показано на рис. 3.108.
543
РАЗРАБОТКА SCADA-СИСТЕМ
Файл Сегмент UltraNet Узел Тег
Файл Сегмент UltraNet Узел Тег
- ULTRANETJ
- FE
22SSEQ
VX0D2
VX0D3
VX0D4
VX0D8
Значение
|0,2880752
Качество
| Good
Э ULTRANETJ
- FE
W0D1
VX0D2
VX0D3
VX0D4
W0D8
-Servei------
ОРС
|Fastwel.PLCNetOPC
Automation Object
|NDgrSetvei.NDgiSivi
Host
Имя
|112-12
IP-адрес
|l92.168.102.111
Tag
Значение
10.1404512
Качество
| Good
Setver
OPC
|Fastwel.PLCNetOPC
Automation Object
|NDgrSetvei.NDgiSivi
Host-----
Имя
J112-12
IP-адрес
]l92.168.102.111
Рис. 3.106. Подключение ОРС-клиента
кОРС-серверу
и восстановление дерева объектов
Рис. 3.107. Добавление нового тега
Сохранить как
Папка: | ОРС Client
Pictures
Недавние
документы
пз
Мои
документы
Имя Файла:
Тип Файла:
| config, sav
| Файлы (“.sav)
| Сохранить |
▼ | Отмена |
Рис. 3.108. Сохранение файла конфигурации
Новый файл конфигурации показан на рис. 3.109. Выход из
программы показан на рис. 3.110.
544
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
|У ОРС-клиент
Файл Сегмент UltraNet Узел Тег
Открыть... --------------------
Сохранить...
Пуск ►
О Стоп
Выход...
VX0D6
ЩЕШ
Tag
Значение
|0.1403618
Качество
|Good
Server
ОРС
|Fastwel.PLCNelOPC
Automation Object
]NDgtSetver.NDgrSrvr
Host
Имя
|112-12
IP-адрес
|l 92.168.102.111
Рис. 3.109. Новый файл конфигурации Рис. 3.110. Выход из программы
3.3.5. Взаимодействие ОРС-сервера,
объекта автоматизации и ОРС-клиента
Основные действия, выполняемые в ОРС-сервере, ОА и ОРС-
клиенте в ответ на действия пользователя, приведены в табл. 3.2.
Таблица 3.2
Действ» и условие возникновения Описание
Запуск ОА или подключение ОРС-клиента к ранее запущенному ОА. Возникает при щелчке мышью по пункту ОА меню в ОРС-клиенте Если ранее ОРС-клиент не устанавливал связь с ОА, то выполняются следующие действия: • считывание IP-адреса и имени мастера; • считывание имени ОРС-сервера; • установление связи с ОА; • запуск ОА или подключение ОРС-клиента к ранее запущенному ОА; • установка невидимости ОА.
Запуск ОРС-сервера на мастере. Возникает при щелчке мышью по пункту меню Файл Пуск —> Automation Object в ОРС-клиенте С помощью метода SetServerName на ОА передается имя ОРС-сервера и ОА осуществляет запуск ОРС-сервера. Перед этим О А проверяет, был ли запущен ОРС-сервер на мастере. Далее происходит считывание ошибки (сетевая переменная Error) выполнения последней операции на ОА. Если произошла ошибка, то есть, по каким-либо причинам ОРС-сервер не был запущен, то происходит отключение ОРС-клиента от ОА.
545
РАЗРАБОТКА SCADA-СИСТЕМ
Продолжение таблицы 3.2
Добавление сегмента в соответствующие массивы и заполнение записей. Щелчок по пункту меню Добавить сегмент в ОРС-клиенте 1. Получение от пользователя имени добавляемого сегмента. Далее с помощью функции GetSegmentlndex выполняется поиск этого сегмента в массиве Segments ОРС-клиента. Если сегмент не был найден, то в ОРС-клиенте выполняются увеличение на единицу длины: • увеличение на единицу длина динамического массива Segments в ОРС-клиенте; • считывание из свойства Segments ОА списка сегментов уже добавленных ранее в массив Sgmt ОА другими ОРС-клиентами; • разбиение в ОРС-клиенте полученной строки на имена сегментов; • поиск в ОРС-клиенте добавляемого сегмента в полученном списке уже существующих сегментов в ОА. 2. Если добавляемого сегмента в ОА еще не было, то есть данный сегмент не был добавлен ранее другими ОРС-клиентами, то вызывается метод ОА и ОА выполняет следующие действия: • запрещается доступ к ОА для других ОРС- клиентов, • устанавливается начальное значение false сетевой переменной Error; • запрещается работа таймера; • изменяется длина динамического массива Sgmt —увеличивается на единицу; • в поле Sgt последнего элемента массива Sgmt сохраняется имя добавленного сегмента; • с помощью функции ServerAddGroup происходит установка связи с сегментом в ОРС-сервере. В поле SegmentHandle последнего элемента массива Sgmt записывается хэндл добавленного в ОРС-сервер сегмента. Далее по этому хэндлу будет осуществляться добавление (связь с тегами в ОРС-сервере) тегов и считывание значений тегов; • если произошла ошибка при добавлении (связи с ОРС-сервером) сегмента в ОА, то уменьшается длина массива Sgmt и в сетевую переменную Error записывается значение true. Если сегмент был успешно добавлен, то в сетевую переменную SegmentExists добавляется имя добавленного сегмента; • если в массиве Items существует хотя бы один тег, то работа таймера разрешается; • разрешается доступ для других ОРС-клиентов кОА.
546
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Продолжение таблицы 3.2
3. В ОРС-клиенте выполняются следующие действия: • заполняются поля последнего элемента массива Segments: имя сегмента, начальное значение длины динамического массива Nodes (0). • в KOMnoHeHTTreeViewl добавляется новый узел с именем добавленного сегмента
Добавление узла (сетевое имя контроллера) в массив Nodes в ОРС. Щелчок по пункту меню Добавить узел в ОРС-клиенте В ОРС-клиенте при этом выполняются следующие действия: -получение полного имени узла в виде Segment.Node, где Segment - имя сегмента, в котором находится узел. Node - имя узла (число в 16-ричной системе счисления от 00 до FF); - с помощью процедуры GetNames выделение из полного имени имен сегмента и узла; - с помощью функции GetSegmentlndex получение номера сегмента в массиве Segments; - с помощью функции GetN odelndex получение номера узла в массиве Nodes; - если такого узла не существует (функция возвращает-1), то: • происходит увеличение длины динамического массива Nodes; • сохраняется имя узла в поле NodeName; • устанавливается начальное значение длины динамического массива • добавляется узел в KOMnoHeHTTreeViewl с именем узла контроллера
Добавление нового тега в соответствующие массивы. Происходит при щелчке мышью по пункту меню Добавить тег в ОРС-клиенте Получение полного имени тега, введенного пользователем. Извлечение имен сегмента, узла и тега из полного имени. Определение номеров сегмента, узла и тега в соответствующих массивах. Если данный сегмент и узел существуют, а тег - нет, то увеличивается длина динамического массива Items, из ОА считывается список существующих тегов, которые ранее были добавлены другими ОРС-клиентами и уже используются. Происходит деление полученной строки на отдельные имена тегов, сохраненных в динами- ческом массиве ms. Поиск добавляемого тега в полученном списке.
547
РАЗРАБОТКА SCADA-СИСТЕМ
Продолжение таблицы 3.2
Если такой тег найден, то происходит сохранение номера найденного тега в списке в поле Number последнего элемента (только что добавленного) в массив Items. Если добавленного тега в списке не оказалось,™ при помощи метода ОА SetltemName происходит добавление тега в массив Items (Items в ОА). При этом в ОА выполняются следующие действия: • запрещается доступ к О А для других ОРС-клиентов; • задается начальное значение переменкой Error (false); • запрещается работа таймера; • увеличивается на единицу длина динамического массива Items; • задается имя тега (поле ItemNarae) и начальное значение (поле ItemValue); • поиск сегмента, в который добавляется тег в массиве Sgmt. Если сегмент найден, то в поле Segments последнего элемента массива Items сохраняется номер найденного сегмента в массиве Sgmt. Сегмент будет найден в любом случае, потому что пользователь должен был добавить сегмент заранее при помощи метода • устанавливается связь добавляемого тега с тегом в ОРС-сервере, сохраняется его хэндл в поле ItemHandle и тип в поле ItemType при помощи функции GroupAddltems; • если по какой-то причине связи не произошло, то в сетевую переменную Error записывается значение true и последний элемент массива Items удаляется. Если же связь была успешной, то к сетевой переменной ItsmsExists (список существующих тегов) добавляется имя вновь добавленного тега; • если существует хотя бы один добавленный в Items тег, то разрешается работа таймера; • разрешается доступ к ОА другим ОРС-клиентам В ОРС-клиенте при этом выполняются следующие действия: • считывается результат выполнения последней операции в ОА (сетевая переменная Error); • получение списка других тегов в ОА; • деление полученного списка на отдельные имена тегов;
548
ГЛАВА 3. Организация взаимодействия программного обеспечения компьютеров...
Окончание таблицы 3.2
• поиск добавленного тега в списке существующих тегов. Если тег найден, то происходит сохранение номера найденного тега в списке в поле Number; • если, при добавлении тега в ОА ошибки не произошло, то полю ItemName последнего элемента массива Items присваивается имя добавленного тега и происходит добавление нового узла в KOMnoHeHTTreeViewl ОРС-клиента с именем тега; • если произошла ошибка, то последний элемент массива Items удаляется
Чтение значений тегов в ОА. Происходит по таймеру Проверяется количество существующих тегов. Если тегов нет, то происходит выход из процедуры: • задается начальное значение строки значений тегов; • последовательно происходит чтение значений существующих тегов из ОРС-сервера с помощью функции ReadOPCGroupItemValue. Значение тега находится по его хэндлу ItemHandle. Если прочитали значение без ошибки, то происходит округление значение тега с точностью до тысячных допей (если тег имеет тип float), если же произошла ошибка, то значению тега присваивается значение 0 (при любом типе тега); • добавление значения тега в переменную Newltems - список значений тегов; • при получении полного списка значений тегов происходит его сохранение в сетевой переменной Items, которую и получает ОРС-клиент при запросе
Чтение значений тегов из ОА ОРС-клиентом. Происходит по таймеру • считывание списка значений тегов из ОА; • деление списка на отдельные значения, сохра- няемые в динамическом массиве ms; • по известным номерам сегмента, узла и тега, которые определяются по выбранному узлу в дереве с, происходит запись в поле ItemValue соответствующего массива Items значения тега. Кроме того, значение тега выводится на экран; • если список пуст, выводится пустая строка
549
Заключение
Сформулируем некоторые выводы, которые можно сделать,
прочитав эту книгу или ее часть.
1. Книга носит исключительно практический характер, по-
скольку авторы изначально к этому стремились. Вся теоре-
тическая составляющая, которая, конечно, имеется в книге,
служит лишь в качестве базиса для получения практических
результатов.
2. Рассмотрены несколько примеров проектирования SCADA-
систем, готовых к применению без каких-либо доработок.
При желании они могут быть доработаны читателем нуж-
ным образом. Авторы приложили значительные усилия
к тому, чтобы материал, изложенный в книге, был макси-
мально понятен:
- практически ни одна строка программного кода не осталась
без комментария: авторы придерживались того правила,
что каждая строка комментария не менее важна, чем строка
программного кода;
- имеет место параллельное описание действий, выполняе-
мых в процедурах и функциях;
- в ряде случаев, особенно это касается главы 3, приводятся
алгоритмы используемых процедур и функций.
3. При подготовке рукописи книги авторы руководствовались
тем положением, что научиться программированию можно
лишь детально изучив несколько полностью законченных
примеров. Такие примеры вы, уважаемый читатель, и на-
шли в этой книге. Авторы решительно отвергают практику
написания современной литературы по программированию:
большинство книг содержат лишь фрагменты программ.
Предполагается, что читатель все остальное «додумает»
сам. Такой подход в значительной степени усложняет по-
нимание материала, изложенного в книге, и часто вызывает
угасание интереса читателя.
550
Библиография
1. Агуров А. П. Последовательные интерфейсы ПК. Практи-
ка программирования. — СПб: БХВ-Петербург, 2004. —
496 с.: ил.
2. Денисенко В. В. Компьютерное управление технологическим
процессом, экспериментом, оборудованием. — М.: Горячая ли-
ния — Телеком, 2009. — 608 с.: ил.
3. Кангин В. В., Козлов В. Н. Аппаратные и программные средства
систем управления. Промышленные сети и контроллеры. — М.:
БИНОМ. Лаборатория знаний, 2010. — 418 с.: ил.
4. Кангин В. В., Кангин М. В., Богов А. Н., Ямолдинов Д. Н. Управ-
ление техническими системами. Контроллер ADAM-5510 и его
программирование в UltraLogik. — Н. Новгород: НГТУ, 2008. —
396 с.: ил.
5. Кангин В. В., Кангин М. В., Ямолдинов Д. Н. Компьюте-
ры в системах управления технологическими процессами. —
Н. Новгород: НГТУ, 2005. — 246 с.: ил.
6. Промышленные сети, контроллеры и модули У СО /
[Кангин В. В. и др.]. — Н. Новгород: НГТУ, 2006. — 418 с.: ил.
7. Кангин В. В., Ложкин Л. Д., Ямолдинов Д. Н. Обмен информаци-
ей в промышленной сети PlcNet // ИКТ. — 2010. — Т. 8, № 3. —
С. 49-54.
8. Кангин В. В., Ложкин Л. Д., Ямолдинов Д. Н. Программная реали-
зация межсетевого шлюза сетей ETHERNET и PLCNET// ИКТ. —
2011. — Т. 9, № 2. — С. 36-41.
9. Delphi и технология СОМ. Мастер-класс / Н. Елманова, С. Трепа-
лин, А. Тенцер. — СПб.: Питер, 2003. — 698 с.
551
Приложения
Приложение i
Список сокращений
АРМ — автоматизированное рабочее место.
АС ОДУ — автоматизированная система оперативно-диспетчерского
управления.
АСКУЭ — автоматизированная система контроля и учета энергоре-
сурсов.
АСУ — автоматизированная система управления.
АСУП — АСУ производством.
АСУТП — АСУ технологическим процессом.
АЦП — аналого-цифровой преобразователь.
БД — база данных.
БД РВ — БД реального времени.
ВОК — волоконно-оптический кабель.
ЖКИ — жидкокристаллический индикатор.
ЗУ — запоминающее устройство.
ИВК — информационно-вычислительный комплекс.
ИМ — исполнительный механизм.
ИТ — информационные технологии.
ЛВС — локальная вычислительная сеть.
МЭК — Международная электротехническая комиссия.
ОА — объект автоматизации
ОС — операционная система.
ОС РВ — ОС реального времени.
ПД — передача данных.
ПК — персональный компьютер.
ППК — промышленный персональный компьютер.
спд — система ПД.
ПЗУ — постоянное ЗУ.
П-регулятор — пропорциональный регулятор.
ПИ-регулятор — пропорционально-интегральный регулятор.
ПИД-регулятор — пропорционально-интегрально-дифференциаль-
ный регулятор.
ПЛ К — программируемый логический контроллер.
ППЗУ — программируемое ПЗУ.
ПО — программное обеспечение.
ПТК — программно-технический комплекс.
РСУ — распределенная система управления.
РВ — реальное время.
552
ПРИЛОЖЕНИЯ
САПР — система автоматизированного проектирования.
САР — система автоматического регулирования.
САУ — система автоматического управления.
СУБД — система управления БД.
ТП — термоэлектрический преобразователь (термопара).
ТС — термо сопротивление.
ТОУ — технологические объекты управления.
УВК — управляющий вычислительный комплекс.
У СО — устройство связи с объектом.
ЦАП — цифро-аналоговый преобразователь.
ЧМИ (HMI) — человеко-машинный интерфейс.
ШИМ — широтно-импульсная модуляция.
СОМ — модель многокомпонентных объектов фирмы Microsoft.
DCOM — распределенная СОМ.
IEC — международная электротехническая комиссия.
ISO — международная организация по стандартизации.
ОРС — стандарт взаимодействия программных компонентов
SCADA-системы.
SCADA-система — система сбора данных и оперативного диспет-
черского управления.
RTU — дистанционное терминальное устройство.
VAC — напряжение переменного тока (в вольтах).
VDC — напряжение постоянного тока (в вольтах).
553
РАЗРАБОТКА SCADA-СИСТЕМ
Приложение 2
Глоссарий
Access Server — сервер доступа. Коммуникационный процессор,
соединяющий асинхронные устройства с локальной или глобальной сетью.
Выполняет синхронную и асинхронную маршрутизацию поддерживающих
его протоколов (сетевой сервер доступа).
ActiveX — технология создания апплетов без применения языка Java,
используемая в Microsoft Windows. Аплеты ActiveX загружаются дольше эк-
вивалентных Java-апплетов, однако они в большей мере используют воз-
можности ОС Windows.
Adapter — плата сетевого интерфейса, предоставляющая возможно-
сти сетевой связи для компьютерной системы.
ANSI — American National Standards Institute — национальный ин-
ститут стандартов США.
API — Application Programming Interface. Интерфейс прикладного
программирования. Спецификация вызовов функций, образующих интер-
фейс некоторой службы.
Applet — небольшая программа — чаще всего в контексте програм-
мирования на языке Java, которая откомпилирована и вставлена в HTML-
страницу.
ARC net (Attached Resource Computer network) — локальная сеть с мар-
керным доступом и пропускной способностью 2,5 Мбит/с, созданная компа-
нией Datapoint Corporation в начале 1980-х годов.
ARP — Adress Resolution Protocol — протокол сетевого уровня, отве-
чающий за взаимное преобразование аппаратных и сетевых адресов.
AS — Autonomous System — сетевая область в виде группы маршру-
тизаторов и сетей, объединенных по иерархическому принципу, находящих-
ся под единым управлением и совместно использующих общую стратегию
маршрутизации.
ASCII (American Standard Code for Information Interchange) — амери-
канский стандартный код обмена информацией. 8-разрядный код для пред-
ставления символов (7 бит + 1 контрольный бит).
ASI — ATM Service Interface — сервисный интерфейс.
ATM — Asychronous Transfer Mode — режим асинхронной передачи.
Международный стандарт поэлементной передачи, когда несколько типов
данных передаются в виде ячеек фиксированной длины (53 байта). Ячейки
обрабатываются на аппаратном уровне, что позволяет сократить задержки
при передаче.
554
ПРИЛОЖЕНИЯ
Backplane — объединительная плата, физическое соедине-
ние между интерфейсным процессором или платой, шинами данных
и шинами распределения питания системного блока компьютера.
Bridge — мост, устройство для соединения и передачи пакетов меж-
ду двумя сетевыми сегментами, использующими один протокол передачи
данных. Мосты действуют на канальном уровне (уровень 2) эталонной мо-
дели OSI. В основном мост фильтрует и передает входящий кадр на основе
его МАС-адреса.
Browser — клиентское приложение с GUI-интерфейсом, программа
просмотра (чтения) гипертекста в формате HTML и преобразования его
для представления пользователю (User).
СВЕМА — Computer and Business Equipment Manufacturers Associa-
tion — ассоциация производителей компьютеров и оргтехники.
CDMA— Code Division Multiple Access — множественный доступ с ко-
довым разделением каналов.
Cluster — кластер. Группа процессоров в многопроцессорной ЭВМ.
Группа, блок, совокупность. Группа блоков памяти на диске, распреде-
ляемая ОС как единое целое. На дискете емкостью 1,44 Мбайт каждый
кластер — один сектор для одного файла.
CORBA— Common Object Request Broker Architecture — архитектура
брокера общих объектных запросов. Стандарт технологии для информаци-
онных систем с распределенной обработкой данных.
CSMA/CD — Carrier Sense Multiple Access Collision Detect — мно-
жественный доступ с контролем несущей и обнаружением конфликтов.
Механизм доступа, при котором устройства, готовые для передачи дан-
ных, сначала проверяют наличие несущей частоты. Если ее нет в течение
заданного промежутка времени, то устройство может приступать к пере-
даче данных. При одновременной передаче двумя устройствами возни-
кает коллизия, которая может быть обнаружена вызвавшими ее устрой-
ствами. Коллизия на некоторое время задерживает передачу данных эти-
ми устройствами. CSMA/CD-доступ используется в Ethernet и стандарте
IEEE 802.3.
DB connector (Data Bus connector) разъем шины данных. Тип разъема,
используемый для подключения последовательного и параллельного кабелей
к шине данных. Их имена записываются в виде DB-x, где х — количество
проводов в разъеме.
DCOM (Distributed Component Object Model) — распределенная ком-
понентная объектная модель. Протокол, позволяющий компонентам про-
граммного обеспечения взаимодействовать непосредственно через сеть.
Разработан фирмой Microsoft и может использоваться с несколькими типа-
ми сетевой транспортировки данных, включая протокол HTTP.
555
РАЗРАБОТКА SCADA-СИСТЕМ
DIN (Deutsche Industrie Norm) — национальный институт стандартов
Германии.
DLL (Dynamic Link Library) — динамически подключаемая библиотека.
DRAM (Dynamic Random Access Memory) — динамическая опера-
тивная память. Оперативная память, где информация хранится в конденса-
торах и периодически обновляется. Модули DRAM имеют более простую
структуру и большую емкость, чем SRAM.
ЕСМА (European Computer Manufacturers Association) — европейская
Ассоциация производителей компьютеров.
EIA (Electronics Industries Association) — ассоциация электронной
промышленности.
EISA (Extended Industry Standard Architecture) — расширенная стандарт-
ная промышленная архитектура. Стандарт шины 32-разрядных микропроцес-
соров, используемый в персональных компьютерах, серверах на их основе и
некоторых рабочих станциях, а также в серверах под управлением ОС UNIX.
E-mail (Electronicmail) — электронная почта. Широко используемое
сетевое приложение передачи текстовых сообщений между конечными
пользователями электронным способом по сетям различного типа с помо-
щью различных сетевых протоколов.
EPROM (Erasable Programmable Read Only Memory) — программи-
руемое с помощью программатора постоянное запоминающее устройство
(ППЗУ), допускающее многократное перепрограммирование. Энергонезави-
симые микросхемы программируются при изготовлении и при необходимо-
сти могут перепрограммироваться.
Ethernet — спецификация широкополосной LAN, предложенная
компанией Xerox Corporation и созданная совместно Xerox, Intel и Digital
Equipment Corporation. Сети Ethernet используют CSMA/CD и могут рабо-
тать с разными типами кабелей с пропускной способностью до 10 Мбит/с.
Спецификация Ethernet аналогична стандартам IEEE 802.3.
Fast Ethernet — обобщенное название группы спецификаций
Ethernet с пропускной способностью до 100 Мбит/с. Fast Ethernet обеспечи-
вает десятикратное увеличение скорости по сравнению со спецификацией
lOBaseT Ethernet, сохраняя формат кадра и МАС-механизмы. Благодаря
унификации в сетях Fast Ethernet возможно использование приложений
и инструментов управления сетью lOBaseT. В основе Fast Ethernet лежит
спецификация IEEE 802.3.
FDDI (Fiber Distributed Data Interface) — кольцевая оптоволоконная
высокоскоростная локальная сеть. Скорость передачи до 100 Мбит/с, то-
пология — двойное кольцо, метод доступа — детерминированный с пере-
дачей маркера. Максимальное число станций — 500 (двойное кольцо) или
1 000 (одинарное кольцо). Расстояние между станциями до 2 км при много-
модовом и до 60 км при одномодовом кабеле.
556
ПРИЛОЖЕНИЯ
Flash memory — флэш-память. Энергонезависимое запоминающее
устройство, содержимое которого стирается и перепрограммируется по
мере необходимости. Флэш-память разработана компанией Intel и лицензи-
рована для использования другими производителями.
FTP (File Transfer Protocol) — протокол передачи файлов. Протокол
уровня приложений, который является частью стека протоколов TCP/IP
и предназначен для передачи файлов между сетевыми узлами.
Gigabit Ethernet — разновидность спецификации Ethernet, одобрен-
ная IEEE комитетом стандартизации 802.3z в 1996 г. для высокоскоростной
передачи данных, до 1000 Мбит/с.
HDLC (High-level Data Link Control) — канальный протокол переда-
чи данных, бит-ориентированный или знак-ориентированный.
HOST — Хост. Компьютер, подключенный к сети.
HTML (HyperText Markup Language) — язык гипертекстовой размет-
ки. Простой язык гипертекстового форматирования, в котором для указания
способа отображения некоторой части документа (например, в Web-браузере)
используются теги.
HTTP (HyperText Transfer Protocol) — протокол передачи гипер-
текстовых файлов. Протокол, используемый Web-браузерами и Web-
серверами для передачи файлов, например текстовых или графических.
IEEE — Institute of Electrical and Electronics Engineers. Институт ин-
женеров по электротехнике и электронике. Занимается созданием коммуни-
кационных и сетевых стандартов. LAN-стандарты IEEE в настоящее время
являются доминирующими для локальных сетей.
Interface — интерфейс:
1. Соединение между двумя системами или устройствами.
2. Сетевое соединение.
3. Граница между смежными уровнями модели OSI.
IP—Internet Protocol, IP-протокол. Протокол сетевого уровня из набора
TCP/IP для объединения сетей без подтверждения соединения. IP-протокол
обладает возможностями адресации, спецификации типа обслуживания,
фрагментации и сборки, а также обеспечения безопасности.
IP-address — IP-адрес или Internet-адрес. 32-разрядный адрес, при-
сваиваемый хостам с помощью протокола TCP/IP. Записывается в виде
4 октетов, разделенных точками (в десятичном формате). Каждый адрес со-
стоит из сетевого номера, дополнительного номера подсети и номера хоста.
Номер сети и подсети используется для маршрутизации, а номер хоста —
для адресации хоста сети или подсети.
IP-datagram (IP-дейтаграмма) — единица (блок) информации, пере-
даваемая в распределенной сети, построенной на базе стека протоколов
TCP/IP. Содержит адреса отправителя и получателя, поля, определяющие
557
РАЗРАБОТКА SCADA-СИСТЕМ
длину дейтаграммы, контрольную сумму заголовка, флаги, отражающие
фрагментацию дейтаграммы, и собственно данные.
IPX (Internetwork Packet Exchange) — базовый протокол NetWare, отве-
чающий за адресацию и маршрутизацию пакетов.
ISO (International Organization for Standardization) — Международная
организация по стандартизации, обеспечившая разработку и поддержку
глобальных стандартов в сфере коммуникаций и обмена информацией. ISO
разработала популярную модель взаимодействия открытых систем OSI.
ITU (International Telecommunications Union) — Международный
союз электросвязи.
LAN (Local Area Network) — локальная сеть. Высокоскоростная
компьютерная сеть, покрывающая относительно небольшую площадь
(до нескольких км). Локальные сети объединяют рабочие станции, пери-
ферийные устройства, терминалы и другие устройства, находящиеся в од-
ном здании или на небольшой территории. Наиболее популярными LAN-
технологиями являются Ethernet, FDDI и Token Ring.
MAC (Media Access Control) — управление доступом к передающей
среде. Низший из двух подуровней канального уровня, определенный
IEEE. МАС-подуровень управляет доступом к совместно используемым но-
сителям. Например, определяет будет ли использоваться передача маркера
или схема разрешения конфликтов.
MAC address — МАС-адрес. Стандартный адрес канального уровня,
который требуется задавать для каждого порта или устройства, подсоеди-
ненного к локальной сети. Другие устройства используют эти адреса для
обнаружения специальных сетевых портов, а также для создания и обнов-
ления таблиц маршрутизации и структуры данных. Длина МАС-адреса —
6 байт, а содержимое регламентируется IEEE. МАС-адреса также называют
аппаратными или физическими адресами.
MPI (MultiPoint Interface) — многоканальный интерфейс.
OSI (Open System Interconnection) — взаимодействие открытых систем.
Международная программа стандартизации, созданная ISO и ITU-T для
разработки стандартов межсетевого обмена данными, способствующих
функциональной совместимости оборудования различных производителей.
PPP (Point-to-Point Protocol) — протокол двухточечного соединения.
РРР зависит от двух протоколов: LCP и NCP.
PROM (Programmable Read Only Memory) — программируемое по-
стоянное запоминающее устройство (ПЗУ), которое можно запрограмми-
ровать с помощью программатора.
Protocol — протокол. Формальное описание набора правил и соглаше-
ний, которые управляют обменом информацией между устройствами по
сети.
558
ПРИЛОЖЕНИЯ
Proxy — прокси (заместитель):
1. Объект, который для большей эффективности дублирует другой
объект.
2. Специальные шлюзы, которые ретранслируют один сеанс Н.323
другому сеансу.
Proxy server — прокси-сервер. Промежуточная программа, которая
действует одновременно как сервер и клиент запросов по поручению других
клиентов. Запросы обслуживаются внутри или за счет передачи их другим
серверам. Прокси-сервер интерпретирует и, если это необходимо, перепи-
сывает сообщение запроса перед его дальнейшей передачей.
RAID — массив резервных дисков. Группа дисков, работающих, как
одно целое. Дисковый массив.
RAM (Random Access Memory) — оперативное запоминающее
устройство (ОЗУ). Запоминающее устройство с произвольной выборкой
(ЗУПВ) для временного хранения информации.
Relay — ретранслятор. Устройство по терминологии OSI, которое
соединяет несколько сетей в единую сетевую систему. На канальном уров-
не (уровень 2) ретранслятором является мост, на сетевом уровне (уро-
вень 3) — маршрутизатор. В отличие от моста и маршрутизатора обеспечи-
вает обслуживание по типу передачи данных с промежуточным хранением,
а не в реальном времени.
Remote system — удаленная система. Система или маршрутизатор,
присоединенные к сети с удаленным доступом и являющиеся инициато-
ром или получателем вызова.
Repeater — повторитель. Устройство для регенерации и распростране-
ния сигналов между двумя сегментами сети.
Ring — кольцо. Соединение нескольких станций по логической коль-
цевой топологии. Информация передается последовательно между активны-
ми станциями. На этой топологии основаны сети Token Ring, FDDI и CDDI.
RISC (Restricted Instruction Set Computer) — архитектура микропро-
цессора с сокращенным набором команд.
RJ connector (Registered Jack Connector) — зарегистрированный кон-
тактный разъем. Стандартные разъемы (RJ-разъемы), которые используют-
ся в телефонных и сетевых соединениях, например, lOBaseT и др. Распро-
страненные RJ-разъемы — RJ-11, RJ-12, RJ-45.
ROM (Read-Only Memory) — постоянное запоминающее устройство
(ПЗУ). Энергонезависимое запоминающее устройство, используемое для
хранения данных, которые заносятся в устройство при его изготовлении.
Router — маршрутизатор. Устройство сетевого уровня, которое опре-
деляет оптимальный маршрут сетевого трафика. Пакеты данных направля-
ются маршрутизатором из одной сети в другую на основании информации
сетевого уровня.
559
РАЗРАБОТКА SCADA-СИСТЕМ
RS-232 — Интерфейс физического уровня. Стандарт EIA/TIA-232,
созданный EIA и TIA, который поддерживает работу на скорости до
64 кбит/с.
RS-422 — электрически сбалансированная реализация стандарта
EIA/TIA-449 для высокоскоростной передачи данных (до 2 Мбит/с). В на-
стоящее время входит в стандарт EIA-530.
Segment — сегмент:
1. Секция сети, ограниченная мостами, маршрутизаторами или ком-
мутаторами.
2. В сети с шинной топологией — непрерывная электрическая цепь,
часто соединенная с другими сегментами с помощью повторите-
лей.
3. По спецификации TCP — одиночный информационный модуль
транспортного уровня.
Server — сервер. Узел сети, обычно локальный, в котором обеспечива-
ется обслуживание сетевых терминалов путем управления распределением
вычислительного ресурса совместного пользования.
Session — сеанс. Взаимосвязанный набор коммуникационных тран-
закций между двумя и более сетевыми устройствами.
Simplex — симплекс. Физическое или логическое соединение двух
точек, при котором осуществляется однонаправленная передача данных
между станцией-источником и станцией-приемником.
Site — сайт. Место, местоположение информации в www, совокупность
страниц, объединенных по смыслу.
SNMP — Simple Network Management Protocol — простой протокол
управления сетью. Протокол, используемый в сетях TCP/IP. SNMP предо-
ставляет средства контроля и управления сетевыми устройствами, конфи-
гурацией, производительностью и безопасностью, а также средства сбора
статистической информации.
Source address — адрес источника. Адрес сетевого устройства, посы-
лающего данные. Адрес сетевого устройства, принимающего данные —
destination address.
SQL (Structured Query Language) — язык структурированных запро-
сов. Международный стандартный язык для описания и доступа к реляци-
онным базам данных.
SRAM (Static Random Access Memory) — статическое запоминающее
устройство с произвольной выборкой. Оперативное запоминающее устрой-
ство, содержимое которого сохраняется при наличии питания. В отличие
от DRAM, SRAM не требует постоянного обновления.
Stub — заглушка. Заменяющая компонента, которая временно исполь-
зуется в программе с тем, чтобы можно было продолжать ее разработку.
560
ПРИЛОЖЕНИЯ
STP (Shielded Twisted-Pair) — экранированная витая пара. Сетевой ка-
бель с двумя изолированными скрученными проводами и экранирующим
слоем, снижающим воздействие электромагнитных помех. Провода могут
быть экранированными и неэкранированными.
Switch — коммутатор. Сетевое устройство, обеспечивающее фильтра-
цию и пересылку кадров с учетом адреса приемника. Коммутатор работает
на канальном уровне модели OSI (уровень 2).
Tag — тег. Идентификационная информация, в том числе номер.
TCP/IP — Transmission Control Protocol / Internet Protocol — Прото-
кол управления передачей данных/ Интернет-протокол. Общее название
протоколов, разработанных Министерством обороны США и использу-
емых исследовательским Управлением Министерства в исследованиях
по объединению сетей. В TCP используется тройное квитирование уста-
новления связи, подтверждение приема сообщений, обеспечение высо-
конадежной дуплексной передачи данных по установленным соедине-
ниям.
Token Ring — локальная сеть с передачей маркера, разработанная и
поддерживаемая компанией IBM. Сеть Token Ring имеет кольцевую топо-
логию и работает со скоростью 4 или 16 Мбит/с по стандарту IEEE 802.5.
(LAN-стандарт, который описывает физический уровень и МАС-подуровень
канального уровня. В нем используется доступ на основе передачи маркеров
по кабелю STP аналогично IBM Token Ring).
Transaction — транзакция. Ориентированный на результат элемент
обработки соединения. Входное сообщение, отражающее некоторое событие
или процесс изменения файла, вызванное входным сообщением.
UDP (User Datagram Protocol) — протокол дейтаграмм пользователя.
Протокол из набора протоколов TCP/IP использует протокол IP для до-
ставки данных. В отличие от TCP протокол UDP обеспечивает обмен дейта-
граммами без подтверждения.
WAP (Wireless Application Protocol) — протокол беспроводных при-
ложений.
WWW (World Wide Web) — Всемирная паутина. Система с архитекту-
рой клиент-сервер, основанная на языке HTML и протоколе HTTP. Большая
сеть серверов Internet, предоставляющая доступ к гипертекстовым доку-
ментам и другие услуги терминалам, работающим с пользовательскими
приложениями, такими, как браузер.
База данных (database) — совокупность данных, хранимых в памя-
ти ПК и отображающих состояние и взаимосвязь объектов.
Банк данных (databank) — информационная система, в которой
реализованы функции централизованного хранения и накопления информа-
ции одной или нескольких баз данных.
561
РАЗРАБОТКА SCADA-СИСТЕМ
Драйвер — программа операционной системы, обслуживающая от-
дельные периферийные устройства, написанная на машинно-ориентиро-
ванном языке программирования.
Дуплексный режим — режим одновременной передачи данных в
обоих направлениях между двумя соединенными точками (физическими
или логическими).
Квитирование — метод управления передачей данных между двумя
устройствами, при котором одно из них передает данные другому только
при условии подтверждения получения запроса на передачу (процесс син-
хронизации приема-передачи).
Корпоративные сети (Enterprise wide networks) — сети масштаба
предприятия.
КЭШ-память — промежуточная память с быстрой выборкой, обра-
щение к которой осуществляется по ассоциативному методу; быстродей-
ствующая память между процессором и основной памятью с наиболее ча-
сто адресуемыми ячейками. В иерархии памяти системы имеются регистры
процессора, которые являются самыми быстродействующими ЗУ, а на более
низком уровне доступности имеются ячейки оперативной памяти. КЭШ
предназначен для выравнивания степени доступности устройств этих
двух типов за счет временного хранения содержимого ячеек оперативной
памяти.
Полудуплексный режим — режим, при котором передача информа-
ции между двумя физическими или логическими объектами в каждый мо-
мент времени осуществляется только в одном направлении. Характеристи-
кой полудуплексного режима является время реверсирования, т. е. время, за
которое производится переход от передачи сообщений к приему и наоборот.
Распределенная база данных — совокупность баз данных, распре-
деленная по взаимосвязанным ресурсам вычислительной системы и доступ-
ная для совместного использования.
РСУ — Распределенная система управления: совокупность микропро-
цессорных устройств (промышленных компьютеров, контроллеров и др.),
объединенных в коммуникационную сеть для обмена и накопления данных
и действующих совместно для решения общей задачи.
СУБД (database management system) — комплекс программных
средств для управления базами данных. К СУБД относятся MS Access 2000,
Visual Fox Pro 5.0, dBase IV и др.
Энкодер — кодирующее устройство, шифратор; программа, выпол-
няющая шифрование.
562
Книги почтой
Заказ можно сделать на сайте издательства
www. infra-e. г и
№ п/п Наименование книги Кол- во
1 Автоматизация проектирования технического обеспечения АСУТП
2 Имитационное моделирование и системы управления
3 Интеллектуальные автоматизированные системы управления технологическими объектами
4 Методы рациональной автоматизации производства
5 Микроконтроллеры для систем автоматики
6 Надежность систем автоматизации
7 Обеспечение безопасности АСУТП в соответствии с современными стандартами
8 Основы автоматизированных систем управления технологическими процессами
9 Порядок создания, модернизации и сопровождения АСУТП
10 Принципы и методы создания надежного программного обеспечения АСУТП
И Разработка программного обеспечения АСУ ТП на основе объектно-ориентированного подхода
12 Разработка SCADA-систем
13 Справочник по настройке промышленных гидростатических уровнемеров
14 Справочник инженера по АСУТП: Проектирование и разработка. Комплект в двух томах.
15 Справочник инженера по КИПиА
16 Управление потенциально опасными технологиями
Учебное издание
Кангин Владимир Венедиктович,
Кангин Михаил Владимирович,
Ямолдинов Дмитрий Николаевич
РАЗРАБОТКА SCADA-СИСТЕМ
Учебное пособие
ISBN 978-5-9729-0319-1
Подписано в печать 25.12.2018
Формат 60x84/16. Бумага офсетная.
Гарнитура «Таймс».
Издательство «Инфра-Инженерия»
160011, г. Вологда, ул. Козленская, д. 63
Тел.: 8(800)250-66-01
E-mail: booking@infra-e.ru
https://infra-e.ru
Издательство приглашает
к сотрудничеству авторов
научно-технической литературы