Содержание


Преамбула

Здесь описывается сервер opcuasrv, являющийся сервером OPCUA общего назначения для пакета crwdaq.
Сервер обеспечивает обмен данными между пакетом crwdaq и клиентами OPCUA, к которому они подключаются.

Сервер состоит из:

Сначала ознакомьтесь с терминологией OPCUA.
Затем узнайте как работает сервер.
См. также заметки по OPCUA.

См. также монитор opcuamon.

Перейти к Содержанию


Терминология OPCUA: server, client, namespace, node, alias

Псевдонимы используются в программе сервера OpcuaSrv для понятности и читабельности, при выполнении программы псевдонимы автоматически заменяются на соответствующие индексы узлов. Псевдонимы должны быть простыми именами по правилам Pascal и не должны быть идентификаторами узлов, т.к. весь смысл псевдонимов состоит в замене nodeId на понятное (для программистов) читабельное имя.

Перейти к Содержанию


Модель данных OPCUA

Сервер OPCUA работает с формализованной моделью данных.

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

С практической точки зрения модель данных - это файл формата .xml, который содержит описание публикуемых сервером данных.

Для создания и редактирования моделей данных есть редактор, который можно вызывать через меню “Старт/Панель Управления OPCUA”, либо командой:

unix grun pyvenv opcua-modeler    # способ 1
unix opcua-cpl opcua-modeler-gui  # способ 2

При создании/редактировании узлов-переменных (в которых, собственно, и находятся данные), следует обращать особое внимание на следующие атрибуты (в окне Attributes editor):

По умолчанию переменные создаются с правами чтения (для клиентов). Если есть необходимость сделать переменные с правами записи (для клиентов), то нужно либо задать флаг AccessLevel/CurrentWrite в модели данных, либо использовать команду @OpcWritable ….

Перейти к Содержанию


Как работает сервер

Программа opcuasrv.py используется в готовом виде, “как есть”.
Всё конфигурирование происходит на уровне оболочки opcuasrv.pas.

Оболочка полностью отвечает за интеграцию сервера в пакет crwdaq.

Для использования сервера нужно правильно сконфигурировать оболочку opcuasrv.pas.
При конфигурировании описываются подключения узлов OPCUA к кривым и тегами пакета crwdaq, а также способы их опроса и обновления.

Общая схема работы сервера

Перейти к Содержанию


Данные и копии данных сервера и клиента

Работая с программами монитора (клиента) opcuamon и сервера opcuasrv всегда надо помнить, что в клиент-серверных программах всегда есть несколько копий данных:

В нормальной ситуации сервер и клиент стараются синхронизовать (обновлять) данные как можно скорее, чтобы все копии данных соответствовали оригиналу (исходным данным сервера). Однако, поскольку сервер и клиент работают в разных процессах, а приемник и передатчик - в разных потоках, всегда существуют задержки с обновлениями, а потому эти четыре копии данных могут отличаться друг от друга. Больше того, в некоторых ситуациях копии гарантированно отличаются. Например, когда клиент инициирует команду записи, заранее предполагается, что текущая копия данных клиента отличается от (желаемых) данных сервера. Целью записи является именно сстремление изменить данные сервера, чтобы затем сервер, прислав обновление клиенту, изменил копию данных клиента на желаемое значение. Больше того, в некоторых ситуациях копии гарантированно отличаются. Например, когда клиент инициирует команду записи, заранее предполагается, что текущая копия данных клиента отличается от (желаемых) данных сервера. Целью записи является именно сстремление изменить данные сервера, чтобы затем сервер, прислав обновление клиенту, изменил копию данных клиента на желаемое значение.

В нашем случае имеется четыре возможные копии данных:

Для понимания работы программ opcuasrv и opcuamon необходимо понимать, что всякое изменение данных происходит путем последовательного изменения (синхронизации) указанных копий данных.

Например, если клиент вызывал команду @OpcNodeSend WaveStarted 1, происходит примерно следующее:

В случае подключения к другому (внешнему) серверу OPCUA вместо серверной программы opcuasrv.py и её оболочки opcuasrv.pas будет выступать внешний сервер (например, SCADA). Но логика остается примерно такой же. Понимание этой логики (наличие нескольких копий данных и синхронизация между ними) позволит избежать ошибок.

Перейти к Содержанию


Оболочка opcuasrv.pas

Оболочка сервера opcuasrv.pas содержит программу DaqPascal, которая отвечает за приемопередачу данных OPCUA от серверной программы opcuasrv.py на стороне пакета crwdaq. Задачей оболочки opcuasrv.pas является интеграция сервера в пакет crwdaq, включая функции запуска остановки, конфигурирования и обмена данными с серверной программой opcuasrv.py.

Перейти к Содержанию


Конфигурирование opcuasrv.pas

Конфигурирование opcuasrv.pas включает в себя:

Имеется пример demo_opcuamon демонстрационной конфигурации для иллюстрации работы сервера opcuasrv. В конфигурации имеется справка.

Перейти к Содержанию


Конфигурация устройства

Для использования сервера opcuasrv надо создать DAQ устройство - например, &OpcuaSrv.

Самый простой способ - использовать default конфигурацию opcuasrv.cfg для стандартного сервера &OpcuaSrv.
Для этого достаточно добавить в конфигурацию код:

[ConfigFileList] ; Default config for &OpcuaSrv
ConfigFile = ~~\resource\daqsite\default\opcuasrv.cfg
[]

Стандартная конфигурация хорошо подходит для большинства прикладных задач.

Можно также сконфигурировать устройство вручную.
Пример конфигурации устройства &OpcuaSrv:

[DeviceList]
&OpcuaSrv = device software program
[&OpcuaSrv]
Comment       = OPCUA_SERVING_PROGRAM
InquiryPeriod = 1
DevicePolling = 10, tpNormal
ProgramSource = ~~\resource\daqsite\opcuaserver\opcuasrv.pas
DebugFlags    = 3
OpenConsole   = 2
StdInFifo     = 128
StdOutFifo    = 128
AnalogFifo    = 1000
DigitalFifo   = 1000
tagStdPyAppStat = Device/&OpcuaSrv/StdPyApp.Stat
tagOpcuaSrvStat = Device/&OpcuaSrv/OpcuaSrv.Stat
StartupScript = [&OpcuaSrv.StartupScript]
FinallyScript = [&OpcuaSrv.FinallyScript]
StartServingSection = [&OpcuaSrv.StartServing]
StartServingPattern = /^(@Opc\w+.*|@Py\w+\s.*)$/i
StartServingTrigger = Welcome to opcuasrv program.
DelayServingTrigger = 5000
FilterTooltipPattern = /^(info:|information:|warn:|warning:|error:|@warning|@error)\s/i
FilterConsolePattern = /^(info:|information:|warn:|warning:|error:)\s/i
tipInfoDelay = 15000
tipWarnDelay = 30000
tipErroDelay = 60000
[]

[TagList]
Device/&OpcuaSrv/StdPyApp.Stat = string  0
Device/&OpcuaSrv/OpcuaSrv.Stat = string  0
[]

Кроме обычных параметров устройства задаются:

Тег tagStdPyAppStat определен так, чтобы гарантированно избежать конфликта имен.
Этот тег содержит строку статистики в формате cookie списка:
rss=RSS;vmd=VMS;gc=GE,OB,C0,C1,C2,GG,GW;poll=PC,PR,PW;ping=PT,PW;
где:
- RSS - resident set size - размер резидентной памяти программы opcuasrv.py в байтах,
- VMS - virtual memory size - размер виртуальной памяти программы opcuasrv.py в байтах,
- GE - флаг (0/1) разрешения сборщика мусора gc.isenabled(),
- OB - счетчик всех (динамических) объектов len(gc.get_objects()),
- C0 - счетчик сборщика мусора для 0-го поколения объектов gc.getcount()[0],
- C1 - счетчик сборщика мусора для 1-го поколения объектов gc.getcount()[1],
- C2 - счетчик сборщика мусора для 2-го поколения объектов gc.getcount()[2],
- GG - счетчик сборщика мусора для неопознанных объектов len(gc.garbage),
- GW - метка времени - когда обновлялась информация о памяти и сборщике мусора,
- PC - poll count - счетчик циклов опроса программы opcuasrv.py,
- PR - poll rate - частота циклов опроса программы opcuasrv.py,
- PW - poll when - метка времени когда обновлялись счетчики опроса,
- PT - ping time - время запроса-ответа в миллисекундах,
- PW - ping when - метка времени когда обновляялся ping.

Тег tagOpcuaSrvStat определен так, чтобы гарантированно избежать конфликта имен.
Этот тег содержит строку статистики в формате cookie списка:
State=ST;ReadRate=RR;SendRate=SR;TimeStamp=TS;
где:
- ST - статус процесса: DEAD,STARTING,PREPARING,RUNNING,STOPPED,RESTARTING.
- RR - частота чтения данных, операций в секунду,
- SR - частота записи данных, операций в секунду,
- TS - метка времени, ms.

Тег tagStdPyAppStat позволяет клиентской программе наблюдать за работой программы opcuasrv.py, чтобы была возможность изучать статистику её работы. При необходимости статистика извлекается из строки.

Перейти к Содержанию


Секции StartupScript, FinallyScript

В этих секциях описываются действия при старте и завершении работы DAQ-системы.
Секция завершения FinallyScript обычно пуста, т.к. после работы делать нечего.
Секция StartupScript должна содержать команды запуска программы opcuasrv.py.
Стандартный вид секции инициализации приведен ниже:

[&OpcuaSrv.StartupScript]                                       ; PyApp startup:
@PyApp Set Launch unix pyvenv                                   ; Command to launch script
@PyApp Set Script ~~/resource/daqsite/opcuaserver/opcuasrv.py   ; Target script pathname
@PyApp Set Params                                               ; Script parameters
@PyApp Set PingCall @PollCount                                  ; Command on ping task
@PyApp Add PingCall @Memory                                     ; Command on ping task
@PyApp Set AutoStart 1                                          ; Enable AutoStart
@PyApp Set PipeSizeKb 128                                       ; Pipe buffer size, KB
@PyApp Set PreferToSend 0                                       ; 0:devPost, 1:devSend
@PyApp Set TimeOutToSend 100                                    ; Timeout to send data, ms
@PyApp Set TimeOutToStop 1000                                   ; Timeout to stop task, ms
@PyApp Set GuardTimerPeriod 5000                                ; Timer period to AutoStart
@PyApp Set PingTimerPeriod 1000                                 ; Timer period to PingCall
@PyApp Set CalcPing 1                                           ; Flag - calc Ping time
[]

[&OpcUaMon.FinallyScript]
[]

В обычной ситуации нет необходимости менять эти секции.

Перейти к Содержанию


Задание псевдонимов

Псевдонимы узлов используются для того, чтобы иметь возможность оперировать понятными (читабельными) именами узлов данных вместо трудно понимаемых индексных идентификаторов. Псевдонимы позволяют сосредоточить все проблемы подключения данных в одном месте, в описании псевдонимов, а дальше работать в терминах предметной области, используя понятные для людей имена узлов.

Псевдонимы узлов задаются в секции устройства (например [&OpcuaSrv]) в формате строк:

Alias name = node

где

Например:

[&OpcuaSrv]
;***************************
;**** Alias to Node mapping:
;***************************
Alias WaveSin       = ns2i2003
Alias WaveCos       = ns2i2004
Alias WaveAmplitude = ns2i2005
Alias WaveFrequency = ns2i2006
Alias WaveNoise     = ns2i2007
Alias WaveStarted   = ns2i2008
[]

При выполнении программы сервера каждый псевдоним заменяется на короткий индексный идентификатор узла.

Настоятельно рекомендуется задавать псевдонимы для всех используемых узлов и работать с псевдонимами, а не с индексными идентификаторами. Это облегчит написание кода и его сопровождение.

Перейти к Содержанию


Список связей задается в секции описания устройства, например, [&OpcuaSrv]. Он задает связи узлов OPCUA с кривыми, тегами, сообщениями и атрибутами.
Это связи указывают, куда и как “укладывать” полученные от сервера данные.

Пример секции связей:

[&OpcuaSrv]
;*****************************************
;**** Link nodes with tags/curves/messages
;*****************************************
Link node WaveSin       with AnalogOutput 0 tag DEMO_OPCUAMON.WAVE.SIN       monitor 5000 message @DevPost &DEMO_OPCUAMON.MAIN.CTRL OpcData $alias $data
Link node WaveCos       with AnalogOutput 1 tag DEMO_OPCUAMON.WAVE.COS       monitor 5000 message @DevPost &DEMO_OPCUAMON.MAIN.CTRL OpcData $alias $data
Link node WaveAmplitude with                tag DEMO_OPCUAMON.WAVE.AMPLITUDE refresh 5000 message @DevPost &DEMO_OPCUAMON.MAIN.CTRL OpcData $alias $data
Link node WaveFrequency with                tag DEMO_OPCUAMON.WAVE.FREQUENCY refresh 5000 message @DevPost &DEMO_OPCUAMON.MAIN.CTRL OpcData $alias $data
Link node WaveNoise     with                tag DEMO_OPCUAMON.WAVE.NOISE     refresh 5000 message @DevPost &DEMO_OPCUAMON.MAIN.CTRL OpcData $alias $data
Link node WaveStarted   with                tag DEMO_OPCUAMON.WAVE.STARTED   refresh 5000 message @DevPost &DEMO_OPCUAMON.MAIN.CTRL OpcData $alias $data
Link node WaveSin       with AnalogInput  0 tag DEMO_OPCUAMON.TEST           trigger 5000 :y message @DevPost &DEMO_OPCUAMON.MAIN.CTRL OpcData $alias $data
[]

Общий формат:

[&OpcuaSrv]
Link node n with (Analog|Digital)(Input|Output) i tag t (monitor|polling|trigger|refresh) p y message m
[]
# n - псевдоним или индексный идентификатор узла OPCUA
# i - номер подключения (Аналог|Цифрового)(Ввода|Вывода)
# t - имя подключеннного к узлу тега
# p - период проверки/обновления данных, мс
# y - необязательный тип триггера (:x|:y|:t), по умолчанию :y
# m - сообщение c подстановкой $node (идентификатор узла),
#     $alias (псевдоним узла), $data (значение данных)

Параметры (Analog|Digital)(Input|Output) i, tag t, message m - необязательны.
Их можно не указывать, если они не нужны.

Наличие ключевых слов Link node … with … - строго обязательно, их порядок имеет значение.

Параметры Link node n with … (monitor|polling|trigger|refresh) p … строго обязательны.

Параметр node n задает псевдоним или (короткий) индексный идентификатор узла.
Рекомендуется всегда использовать псевдонимы - так будет легче понимать код.

Параметры (monitor|polling|trigger|refresh) p y задают способ опроса:

Заметим, что при указании периода опроса p=0 чтение/запись по таймеру отключается.
Это может быть полезно, чтобы читать/записывать данные только по (внешним) событиям.

При работе по внешним событиям чтение/запись инициируется командами:

Перейти к Содержанию


Объяснение режимов и триггеров

Для понимания работы сервера следует помнить, что клиент OPCUA - имеет лишь копию
данных, которыми владеет сервер. Поэтому клиент не может изменить данные сразу, вместо этого он
посылает серверу команду (запрос) на изменение данных на сервере. Затем, если сервер одобрил
изменения, обновленные данные приходят клиенту по подписке (либо считываются клиентом явно),
чтобы клиент обновил свою копию данных.

Режим monitor p с периодом таймера p является основным методом чтения (наблюдения) данных.
Для правильной работы на узел должна быть оформлена подписка на обновления @OpcBooking ….
Таймер p гарантирует, что чтение данных будет выполняться не реже p миллисекунд,
даже если сервер долго не обновляет данные. При нулевом значении p таймер отключается.
Нулевой таймер можно использовать для работы по событиям (посылкой явных команд чтения).
При работе клиент сохраняет прочитанные с сервера данные в подключенные кривые
(Analog|Digital)Output … и теги Tag ….

Пример:

# Чтение узла WaveSin по подписке, но не реже 5сек
Link node WaveSin with AnalogOutput 0 monitor 5000

Режим polling p с периодом таймера p является вспомогательным методом чтения редко изменяемых данных.
Таймер p обеспечивает чтение данных с периодом p миллисекунд, даже если нет подписки на обновления.
При нулевом значении p таймер отключается, автоматических обновлений при этом не происхоит.
Нулевой таймер можно использовать для работы по событиям (посылкой явных команд чтения).
При работе клиент сохраняет прочитанные с сервера данные в подключенные кривые
(Analog|Digital)Output … и теги Tag ….

Пример:

# Чтение узла WaveSin без подписки, раз в 5сек
Link node WaveSin with AnalogOutput 0 polling 5000

Режим trigger p y с периодом таймера p является основным методом записи (и наблюдения) данных.
Для правильной работы на узел должна быть оформлена подписка на обновления @OpcBooking ….
Таймер p гарантирует, что запись и чтение данных будет идти не реже p миллисекунд,
даже если сервер долго не обновляет данные. При нулевом значении p таймер отключается.
Нулевой таймер можно использовать для работы по событиям (посылкой явных команд записи/чтения).
Параметр y со значением по умолчанию :y задает источник триггера на запись.
Источник :y - триггер записи при изменении координаты y подключенной кривой (Analog|Digital)Input.
Источник :x - триггер записи при изменении координаты x подключенной кривой (Analog|Digital)Input.
Источник :t - триггер записи при изменении значения t подключенного тега.
При этом в подключенную кривую (Analog|Digital)Output … или тег Tag … идет сохранение
значений узла, прочитанных с сервера, аналогично режиму monitor p.

Пример:

# Запись/чтение узла WaveSin по триггеру :y, но не реже 5сек
Link node WaveSin with AnalogInput 0 tag Demo.WaveSin trigger 5000 :y

Режим refresh p y работает аналогично режиму trigger, только триггер на запись по
изменению значений не используется, а запись идет по таймеру p (или по внешним событиям).
Источник триггера играет роль только при подключении тега - он указывает, что при записи данные
следует брать из тега, если указано значение источника триггера :t.
При этом в подключенную кривую (Analog|Digital)Output … или тег Tag … идет сохранение
значений узла, прочитанных с сервера, аналогично режиму monitor p.

Пример:

# Запись/чтение узла WaveSin по таймеру 5сек
Link node WaveSin with AnalogInput 0 tag Demo.WaveSin refresh 5000 :y

Наконец, при указании нулевого таймера p чтение/запись ведется по событиям,
т.е. по сообщениям @OpcNodeRead …, @OpcNodeSend …, @OpcNodePoke ….

Перейти к Содержанию


Задание секции StartServing

В этой секции описываются команды, вызываемые при старте сервера. Исполняются только команды, подходящие под шаблон StartServingPattern. Эти команды посылаются в консоль оболочки opcuasrv.pas для выполнения.

Монитор стартует только после получения от серверной программы opcuasrv.py ключевой (триггерной) строки StartServingTrigger, а также после задержки на заданную величину DelayServingTrigger миллисекунд. Это нужно для правильного запуска серверной программы, т.к. ей требуется некоторое время для проведения внутренней инициализации.

В секции старта сервера задаются параметры подключения к серверу OPCUA, а также оформляется подписка на обновление нужных для работы узлов. Затем делается старт цикла опроса сервера для начала обмена данными. Также, если нужно, делается запись начальных значений некоторых узлов.

Пример типичной секции старта сервера:

[&OpcuaSrv.StartServing]                                        ; Start serving actions:
@OpcServName OpcuaSrv                                           ; Assign server name
@OpcXmlModel ../daqpas/wave-demo-server.xml                     ; Data Model XML File
@OpcNamespace http//freeopcua/defaults/modeler                  ; Assign server namespace
@OpcEndpoint opc.tcp://0.0.0.0:4840/daqgroup/demo               ; Set server endpoint URL
@OpcBooking  /how=(monitor|trigger|refresh)/i                   ; Subscribe (monitor|trigger|refresh) nodes
@OpcSubInter 1                                                  ; Subscription update interval, ms
@UseShortKey 1                                                  ; Flag to use short node id
@OpcServing                                                     ; Start serving
@OpcNodePoke WaveAmplitude :t                                   ; Assign node value from linked tag
@OpcNodePoke WaveFrequency :t                                   ; Assign node value from linked tag
@OpcNodePoke WaveNoise :t                                       ; Assign node value from linked tag
@OpcNodeSend WaveStarted 1                                      ; Write node value
[]

Перейти к Содержанию


Комады оболочки opcuasrv.pas

Ниже описаны команды консоли оболочки opcuasrv.pas.

Следует специально отметить, что консоли оболочки opcuasrv.pas и сервера opcuasrv.py - это две разные консоли для двух разных программных потоков, из не надо путать друг с другом.

Перейти к Содержанию


Команда @OpcServName name

Команда @OpcServName name задает условное имя name для сервера OPCUA.

Например:

@OpcServName  OpcuaSrv

Имя сервера OPCUA следует задавать в самом начале, до старта сервера командой @OpcServing.

Перейти к Содержанию


Команда @OpcNamespace n

Команда @OpcNamespace n задает имя адресного пространства n для модели данных сервера OPCUA.

Например:

@OpcNamespace http//freeopcua/defaults/modeler

Важно, чтобы имя адресного пространства n совпадало с именем модели данных, загруженной из XML файла командой @OpcXmlModel. Иначе сервер не сможет отыскать данные для подключения.

Имя адресного пространства сервера OPCUA следует задавать в самом начале, до старта сервера командой @OpcServing.

Перейти к Содержанию


Команда @OpcEndpoint url

Команда @OpcEndpoint url задает адрес URL для точки подключения сервера OPCUA.

Например:

@OpcEndpoint  opc.tcp://localhost:4840/daqgroup/demo

Здесь 4840 - стандартный TCP порт OPCUA, зарегистрированный в IANA как OPC UA Connection Protocol. См. service-names-port-numbers.txt.

Адрес точки подключения сервера OPCUA следует задавать в самом начале, до старта сервера командой @OpcServing.

Перейти к Содержанию


Команда @OpcBooking pattern

Команда @OpcBooking pattern задает шаблон pattern (регулярное выражение) для подписки на обновления данных от сервера OPCUA.

Например:

@OpcBooking  /.*/i                              # подписка на все объявленные узлы
@OpcBooking  /Wave.*/i                          # подписка на все узлы с псевдонимами Wave*
@OpcBooking  /how=(monitor|trigger|refresh)/i   # подписка на узлы с типом опроса (monitor|trigger|refresh)

При подписке на данные сервер OPCUA будет присылать уведомлении об изменении данных при их обновлении на стороне сервера.

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

Подписку на обновления данных сервера OPCUA следует делать до старта сервера командой @OpcServing.

Перейти к Содержанию


Команда @OpcServing

Команда @OpcServing запускает цикл опроса серверной программы opcuasrv.py. Перед запуском необходимо задать (как минимум) адрес сервера @OpcAddress и шаблоны для подписки узлов @OpcBooking.

Например:

@OpcServing   # запуск сервера

После запуска сервера должен начаться обмен данными с сервером OPCUA.

Перейти к Содержанию


Команда @OpcNodeRead node

Команда @OpcNodeRead node посылает серверной программе opcuasrv.py запрос на чтение узла node. В качестве имени узла задается псевдоним или индексный идентификатор узла.

Например:

@OpcNodeRead WaveSin    # чтение узла с псевдонимом WaveSin

Команда чтения используется, если надо прочитать конкретный узел досрочно. Это может быть узел, на который не была оформлена подписка, либо подписка была оформлена, но данные почему-то долго не обновлялись.

При успешном выполнении данные будут (через некоторое время) присланы сервером.

Команда чтения работает только после старта цикла опроса сервера.

Перейти к Содержанию


Команда @OpcNodeSend node value

Команда @OpcNodeSend node value посылает серверной программе opcuasrv.py запрос на запись в узел node значения value на стороне сервера OPCUA. В качестве имени узла node задается псевдоним или индексный идентификатор узла. Новое значение value передается в виде строки.

Например:

@OpcNodeSend WaveAmplitude 3.14    # запись в узел с псевдонимом WaveAmplitude значения 3.14

Команда записи используется, чтобы задать узлу (переменной на стороне сервера) новое значение, явно заданное в аргументе команды.

При успешном выполнении данные будут (через некоторое время) обновлены на стороне сервера. Соответственно придет уведомление об изменении данных (если оформлена подписка). Надо, однако, быть готовым к тому, что сервер может отклонить изменение, если оно не разрешено, поэтому обновление данных может и не произойти.

Команда записи работает только после старта цикла опроса сервера.

Перейти к Содержанию


Команда @OpcNodePoke node source

Команда @OpcNodePoke node source посылает серверной программе opcuasrv.py запрос на запись в узел node значения, взятого из источника source.

В качестве имени узла node задается псевдоним или индексный идентификатор узла.

Значениями источника source могут быть:

Например:

@OpcNodePoke WaveAmplitude :t    # запись в узел с псевдонимом WaveAmplitude значения из присоединенног тега

Команда записи используется, чтобы задать узлу (переменной на стороне сервера) новое значение, взяятое из присоединенного тега или кривой (вместо указания явного значения).

Команда записи работает только после старта цикла опроса сервера.

Перейти к Содержанию


Команда @OpcInform topic

Команда @OpcInform topic печатает в консоли серверной оболочки opcuasrv.pas информацию на тему topic:

Пример вывода команды @OpcInform:

@opcinform
&OPCUAMON ! No topics specified.
&OPCUAMON : Available topics are:
&OPCUAMON :  Links - table of node links.
&OPCUAMON :  Alias - alias to node table.
&OPCUAMON :  Books - nodes booking table.
&OPCUAMON :  How   - node trig how table.
&OPCUAMON :  *     - all listed topics.
@opcinform *
&OPCUAMON : Alias to Node table:
 wavenoise     = ns2i2007
 wavesin       = ns2i2003
 wavecos       = ns2i2004
 wavefrequency = ns2i2006
 wavestarted   = ns2i2008
 waveamplitude = ns2i2005
&OPCUAMON : Table of Node links:
 wavenoise     - how=refresh 5000;tag=264;ali=wavenoise;nod=ns2i2007;msg=@DevPost &DEMO_OPCUAMON.MAIN.CTRL OpcData $alias $data;
 wavesin       - how=monitor 5000;nao=0;tag=265;ali=wavesin;nod=ns2i2003;msg=@DevPost &DEMO_OPCUAMON.MAIN.CTRL OpcData $alias $data;
 wavecos       - how=monitor 5000;nao=1;tag=266;ali=wavecos;nod=ns2i2004;msg=@DevPost &DEMO_OPCUAMON.MAIN.CTRL OpcData $alias $data;
 wavefrequency - how=refresh 5000;tag=262;ali=wavefrequency;nod=ns2i2006;msg=@DevPost &DEMO_OPCUAMON.MAIN.CTRL OpcData $alias $data;
 wavestarted   - how=refresh 5000;tag=261;ali=wavestarted;nod=ns2i2008;msg=@DevPost &DEMO_OPCUAMON.MAIN.CTRL OpcData $alias $data;
 waveamplitude - how=refresh 5000;tag=263;ali=waveamplitude;nod=ns2i2005;msg=@DevPost &DEMO_OPCUAMON.MAIN.CTRL OpcData $alias $data;
&OPCUAMON : Nodes Booking table:
 wavenoise     = Booked
 wavesin       = Booked
 wavecos       = Booked
 wavefrequency = Booked
 wavestarted   = Booked
 waveamplitude = Booked
&OPCUAMON : Node Trig How table:
 wavenoise     = refresh
 wavesin       = monitor
 wavecos       = monitor
 wavefrequency = refresh
 wavestarted   = refresh
 waveamplitude = refresh

Перейти к Содержанию


Монитор opcuasrv.py

Здесь описывается серверная программа opcuasrv.py - сервер для публикации данных OPCUA.
Он написан на языке Python с использованием модулей asyncua и pycrwkit.

Сервер opcuasrv.py используется в готовом виде, “как есть”.
Всё конфигурирование происходит на уровне оболочки opcuasrv.pas.

Перейти к Содержанию


Вызов программы opcuasrv.py

Программа opcuasrv.py вызывается командами:

unix pyvenv opcuasrv.py                                 # простой вызов без параметров
unix pyvenv opcuasrv.py -u opc.tcp://localhost:4840     # вызов с указанием адреса сервера
unix pyvenv opcuasrv.py --url opc.tcp://localhost:4840  # вызов с указанием адреса сервера

Команда unix pyvenv … вызывает программу в (правильном) виртуальном окружении.
Необязательная опция -u или --url задает адрес сервера для подключения.
Сервер подключения может быть задан позже командой @OpcServAddr.

Перейти к Содержанию


Команды и сообщения opcuasrv.py

Ниже описаны команды консоли серверной программы opcuasrv.py.

Следует специально отметить, что консоли оболочки opcuasrv.pas и сервера opcuasrv.py - это две разные консоли для двух разных программных потоков, из не надо путать друг с другом.

Управление программой opcuasrv.py и обмен данными идет с помощью консольных команд, посылаемых клиентом в поток stdin и ответных сообщений от программы в потоке stdout. Формат команд и сообщений - текстовый, в кодировке utf8, с обычным разделением на строки с помощью разделителя строк EOL, равного LF под Unix или CRLF под Windows.

Команды задаются в формате DaqScript:

Пример команд:

@Help           # команда без аргументов
@Exit 1         # команда с аргументом 1

Перейти к Содержанию


Команда @Help

Печатает справку по командам.

@help
 @Help             -  print this help
 @Exit n           -  exit with code n
 @PingEcho s       -  print echo (for testing)
 @PollCount        -  print polling loop counter
 @PollPeriod n     -  set polling loop period n ms
 @TermOnError n    -  terminate on error flag (0/1)
 @Memory           -  get process memory rss,vms,gc
 @OpcServName n    -  get/set server name (n), like OpcuaSrv
 @OpcEndpoint u    -  get/set server endpoint URL (u), like opc.tcp://0.0.0.0:4840/daqgroup/crwdaq/server
 @OpcServAddr u    -  get/set server endpoint URL (u), like opc.tcp://0.0.0.0:4840/daqgroup/crwdaq/server
 @OpcNamespace n   -  get/set server namespace (n), like http//freeopcua/defaults/modeler
 @OpcNspArray      -  get list of namespaces available on server
 @OpcNspIndex      -  get index of server namespace in list of namespaces
 @OpcXmlModel x    -  get/set server XML model (x), like /mnt/data/home/alex/projects/sandbox/opcua/opcua_test/opcuasrv.xml
 @OpcWritable n    -  make client`s writable node (n), like ns=2;i=13 or ns2i13
 @OpcDataBook n    -  subscribe data change of node (n), like ns=2;i=13 or ns2i13
 @UseShortKey f    -  flag (0/1) to use short key (ns2i13 instead of ns=2;i=13)
 @OpcSubInter p    -  subscription interval (period) ms, default is 100
 @OpcStartSrv      -  start OPCUA server to publish nodes data
 @OpcDataVary n v  -  notification on node (n) changed to value (v)
 @OpcGotEvent e    -  notification on got event (e)
 @OpcDataSend n v  -  write node (n) value (v)
 @OpcDataRead n    -  read node (n) value

Перейти к Содержанию


Команда @Exit n

Команда @Exit n завершает программу с кодом выхода n. Код выхода необязателен, по умолчанию 0.

Ответное сообщение: @Exit n - уведомляет о выполнении команды.

Перейти к Содержанию


Команда @PingEcho s

Команда @PingEcho s выводит в консоль эхо - т.е. саму себя. Применяется для проверки связи (ping) и измерения времени отклика.

Ответное сообщение: @PingEcho s - уведомляет о выполнении команды.

Перейти к Содержанию


Команда @PollCount

Команда @PollCount используется для чтения счетчика циклов. Счетчик циклов служит для оценки частоты цикла опроса команд и сообщений.

Ответное сообщение: @PollCount n - возвращает значение счетчика циклов n.

Перейти к Содержанию


Команда @PollPeriod n

Команда @PollPeriod n используется для чтения/записи периода опроса n цикла опроса команд и сообщений. При отсутствии аргумента происходит чтение, при наличии - запись и чтение периода опроса.

Ответное сообщение: @PollPeriod n - возвращает значение периода опроса n в миллисекундах (мс).

Начальное значение периода опроса - 4 мс.

Перейти к Содержанию


Команда @TermOnError n

Команда @TermOnError n читает/задает флаг n = (0/1) для обработки ошибок. Если флаг установлен, при ошибках (исключениях) программа прекращает выполнение.

Ответное сообщение: @TermOnError n - возвращает значение флага.

Начальное значение флага - 0.

Перейти к Содержанию


Команда @Memory

Команда @Memory используется для чтения счетчиков памяти.

Ответное сообщение: @Memory rss=R; vms=V; gc=G - возвращает значение счетчика резидентной памяти R и виртуальной памяти V в байтах, а также счетчиков “сборщика мусора” (garbage collection) G.

Счетчики сборщика мусора имеет формат gc=ge,go,g0,g1,g2,gg:

Перейти к Содержанию


Команда @OpcServName

Команда @OpcServName n задает имя сервера n.

По умолчанию имя сервера OpcuaSrv.

Имя сервера должно задаваться ДО старта сервера командой @OpcStartSrv.

Перейти к Содержанию


Команда @OpcEndpoint

Команда @OpcEndpoint u задает адрес точки подключения сервера u.

Параметр u имеет формат URL (universal resource location), например, opc.tcp://localhost:4840/daqgroup/crwdaq/server. В качестве имени сервера допустимо использовать IP адрес 0.0.0.0, что означает “все сетевые адаптеры на данном компьютере”. Также можно указывать имя компьютера (hostname), ссылку localhost или IP адрес конкретного сетевого адаптера.

Для связи можно использовать стандартный порт OPCUA номер 4840. Этот порт официально зарегистрирован в организации IANA под записью opcua-tcp 4840 tcp "OPC UA Connection Protocol" [OPC_Foundation] [Randy_Armstrong] 2018-01-04. Либо можно использовать альтернативный порт, например, 16550.

Альтернативным способом задания адреса точки подключения является опция командной строки -u url или --url url при вызове прграммы. В этом случае команду можно не использовать.

По умолчанию используется адрес opc.tcp://0.0.0.0:4840/daqgroup/crwdaq/server.

Адрес точки подключения сервера должен задаваться ДО старта сервера командой @OpcStartSrv.

Перейти к Содержанию


Команда @OpcServAddr

Команда @OpcServAddr u является синонимом команды @OpcEndpoint u.

Перейти к Содержанию


Команда @OpcNamespace

Команда @OpcNamespace n задает имя адресного пространства (namespace) n.

У сервера может быть несколько адресных пространств, в которых расположены поименованные объекты. Команда задает имя адресного пространства модели данных, которое будет публиковать сервер.

Предполагается, что модель данных загружается из XML файла командой @OpcXmlModel x. Имя адресного пространства x должно совпадать с именем адресного пространства, которое сохранено в XML файле модели данных, иначе сервер не сможет отыскать нужные данные.

По умолчанию используется адресное пространство http//freeopcua/defaults/modeler.
Это имя адресного пространства по умолчанию для программы opcua-modeler,
которая используется для создания и редактирования модели данных.

Имя адресного пространства сервера должно задаваться ДО старта сервера командой @OpcStartSrv.

Перейти к Содержанию


Команда @OpcNspArray

Команда @OpcNspArray выводят список адресных пространств (namespace) сервера. Она носит информативный характер.

Перейти к Содержанию


Команды @OpcNspIndex

Команда @OpcNspIndex выводят индекс заданного адресного пространства (namespace) в массиве адресных пространств сервера. Она носит информативный характер.

Возвращаемый индекс используется для построения индексных идентификаторов ns=…, используемых для доступа к данным.

Перейти к Содержанию


Команды @OpcXmlModel

Команда @OpcXmlModel x задает имя x для XML файла модели данных.

Имя файла должно быть задано абсолютным путем файла. Оно может включать переменные среды окружения, например, $CRW_DAQ_CONFIG_HOME_DIR/opcuasrv.xml.

Задание файла модели данных является обязательным для работы сервера.

Альтернативным способом задания файла является опция командной строки -x file.xml или --xml file.xml при вызове прграммы. В этом случае команду можно не использовать.

Имя файла модели данных сервера должно задаваться ДО старта сервера командой @OpcStartSrv.

Перейти к Содержанию


Команды @OpcWritable

Команда @OpcWritable n задает для узла n разрешение на запись данных клиентами. Если узел не имеет разрешения, попытка записи значения узла клиентами будет отвергнута. При этом запись данных сервером разрешена всегда.

Другим способом задать для узла разрешение на запись данных клиентами является установка флага CurrentWrite в свойстве AccessLevel и UserAccessLevel данного узла. Это можно сделать при редактировании модели данных в редакторе opcua-modeler.

Перейти к Содержанию


Команда @OpcDataBook n

Команда @OpcDataBook n служит для подписки узла (node) с идентификатором n на уведомления об изменении значения.
Идентификатор n задается в полной форме вида (например) ns=2;i=13 или короткой форме ns2i13.

Здесь:

Ответное сообщение: @OpcDataBook n - уведомляет о выполнении команды.

Подписка должна выполняться (строго) до старта сервера командой @OpcStartSrv.

В результате подписка сервер OPCUA будет посылать уведомления @OpcDataVary n v про каждом изменении данных узла n на значение v.

Перейти к Содержанию


Команда @UseShortKey f

Команда @UseShortKey f читает/задает флаг f = (0/1) для формата печати идентификаторов узлов.
Если флаг установлен, при печати используется короткий формат (ns2i13 вместо ns=2;i=13).

Ответное сообщение: @UseShortKey f - возвращает значение флага.

Начальное значение флага - 0.

Перейти к Содержанию


Команда @OpcSubInter p

Команда @OpcSubInter p читает/задает интервал (период) опроса p для проверки обновления подписки узлов (subscription interval).
Этот интервал определяяет частоту (периодичность) обновления данных на стороне клиента.

Данные клиента будут обновляться с учетом двух факторов:

Другими словами, клиент будет получать обновления данных по факту изменения данных на стороне сервера, но не чаще интервала обновления.

Например, при значении @OpcSubInter 1000 (интервал одна секунда) обновления будут приходить с периодичностью раз в секунду - но только для тех узлов, которые изменились за эту секунду.

Ответное сообщение: @OpcSubInter p - возвращает значение интервала обновления подписки.

Начальное значение интервала подписки - 100.

Для получения максимальной частоты обновления используйте интервал обновления @OpcSubInter 1.
В этом случае обновление данных на стороне клиента будет максимально приближено к обновлению данных на сервере.

Значение интервала обновления должно быть задано командой @OpcSubInter ДО старта сервера командой @OpcStartSrv. Попытка изменения интервала обновления после старта сервера будет (молча) проигнорирована.

Перейти к Содержанию


Команда @OpcStartSrv

Команда @OpcStartSrv стартует сервер, т.е. начинает обмен данными, на которые была оформлена подписка.
После старта сервера оформлять новые подписки уже нельзя вплоть до перезапуска программы сервера.

Ответное сообщение: @OpcStartSrv s - возвращает статус сервера s = (0|1).

Перейти к Содержанию


Сообшение @OpcDataVary n v

Сообшение @OpcDataVary n v посылается при получении от сервера обновления узла с идентификатором n с новым значением v.
Это сообщение является основным способом передачи данных от сервера при их изменении.

Клиент должен обновлять свои (локальные) копии данных при получении этого сообщения.

Перейти к Содержанию


Сообшение @OpcGotEvent e

Сообшение @OpcGotEvent e посылается при получении от сервера события e.

Клиент должен выполнять обратотку событий при получении этого сообщения.

Перейти к Содержанию


Сообшение @Error class e - m

Сообшение @Error class e - m посылается при возникновении ошибки (исключения) класса e с сообщением m.
При этом программа может продолжить выполнение, если исключение было перехвачено и обработано.
Но возможны и фатальные ошибки, при которых программа прекращает работу.

Клиент должен выполнять обработку ошибок при получении этого сообщения.

Перейти к Содержанию


Команда @OpcDataSend n v

Команда @OpcDataSend n v посылается для записи в узел с идентификатором n значения v.
Сервер должен выполнить запись данных узла при получении этой команды.
Команда работает только после старта сервера командой @OpcStartSrv.

Ответное сообщение: @OpcDataSend n v - уведомляет о выполнении команды.

Перейти к Содержанию


Команда @OpcDataRead n

Команда @OpcDataRead n инициирует непоследственное (без подписки) чтение значения узла с идентификатором n.
Используется для чтения редко изменяемых данных без подписки, либо для досрочного чтения данных.
Команда работает только после старта сервера командой @OpcStartSrv.

Ответное сообщение: @OpcDataRead n v - возвращает идентификатор узла n и его значение v.

Перейти к Содержанию


Пример сеанса работы opcuasrv.py

Здесь приведен пример сеанса работы opcuasrv.py с указанием направления передачи:

> Start opcuasrv.
> Type '@Exit' to terminate.
> Type '@Help' to show help.
> Welcome to opcuasrv program.
< @OpcEndpoint  opc.tcp://0.0.0.0:4840/daqgroup/opcuasrv
< @OpcNamespace http//freeopcua/defaults/modeler
< @OpcServName  OpcuaSrv
< @OpcXmlModel  opcuasrv
< @UseShortKey  1
< 
< @OpcDataBook ns2i2003
< @OpcDataBook ns2i2004
< @OpcDataBook ns2i2005
< @OpcDataBook ns2i2006
< @OpcDataBook ns2i2007
< @OpcDataBook ns2i2008
< 
< @OpcWritable ns2i2005
< @OpcWritable ns2i2006
< @OpcWritable ns2i2007
< @OpcWritable ns2i2008
< 
< @OpcStartSrv
> @OpcEndpoint opc.tcp://0.0.0.0:4840/daqgroup/opcuasrv
> @OpcNamespace http//freeopcua/defaults/modeler
> @OpcServName OpcuaSrv
> @OpcXmlModel /mnt/data/home/alex/projects/daqgroup/suite/crwdaq/resource/daqsite/opcuaserver/opcua_test/opcuasrv.xml
> @UseShortKey 1
> @OpcDataBook ns=2;i=2003
> @OpcDataBook ns=2;i=2004
> @OpcDataBook ns=2;i=2005
> @OpcDataBook ns=2;i=2006
> @OpcDataBook ns=2;i=2007
> @OpcDataBook ns=2;i=2008
> @OpcWritable ns=2;i=2005
> @OpcWritable ns=2;i=2006
> @OpcWritable ns=2;i=2007
> @OpcWritable ns=2;i=2008
> @OpcStartSrv 1
> @OpcNspArray http://opcfoundation.org/UA/, urn:freeopcua:python:server, http//freeopcua/defaults/modeler
> @OpcNspIndex 2
> WARNING:asyncua.server.server:Endpoints other than open requested but private key and certificate are not set.
> @OpcNodeId ns2i2003 ns=2;i=2003 WaveSin 0:Root/0:Objects/2:DaqGroupPublic/2:WaveDemo/2:WaveSin
> @OpcNodeId ns2i2004 ns=2;i=2004 WaveCos 0:Root/0:Objects/2:DaqGroupPublic/2:WaveDemo/2:WaveCos
> @OpcNodeId ns2i2005 ns=2;i=2005 WaveAmplitude 0:Root/0:Objects/2:DaqGroupPublic/2:WaveDemo/2:WaveAmplitude
> @OpcNodeId ns2i2006 ns=2;i=2006 WaveFrequency 0:Root/0:Objects/2:DaqGroupPublic/2:WaveDemo/2:WaveFrequency
> @OpcNodeId ns2i2007 ns=2;i=2007 WaveNoise 0:Root/0:Objects/2:DaqGroupPublic/2:WaveDemo/2:WaveNoise
> @OpcNodeId ns2i2008 ns=2;i=2008 WaveOn 0:Root/0:Objects/2:DaqGroupPublic/2:WaveDemo/2:WaveOn
> Try to subscribe 6 items
> INFO: Subscription done for 6 node(s).
> @OpcDataVary ns2i2003 None
> @OpcDataVary ns2i2004 None
> @OpcDataVary ns2i2005 None
> @OpcDataVary ns2i2006 None
> @OpcDataVary ns2i2007 None
> @OpcDataVary ns2i2008 None
> @OpcWritable ns2i2005
> @OpcWritable ns2i2006
> @OpcWritable ns2i2007
> @OpcWritable ns2i2008
> @OpcDataRead ns2i2003
< @OpcDataSend ns2i2003 3.14
< @OpcDataRead ns2i2003
< @OpcDataSend ns2i2003 3.0
> @OpcDataSend ns2i2003 3.0
> @OpcDataRead ns2i2003 3.0
> @OpcDataSend ns2i2003 3.14
> @OpcDataRead ns2i2003 3.14
> @OpcDataVary ns2i2003 3.0
> @OpcDataVary ns2i2003 3.14
< @Exit
> Program terminated. Press Enter to exit.
> @Exit 0

Перейти к Содержанию


Желаем успешного использования opcuasrv.


CRW-DAQ Copyright (c) 2001-2025 Alexey Kuryakin