UniSet 2.32.1
Поддержка работы с OPC-UA

Общее описание OPCUAServer

Данная реализация построена на использовании проекта https://github.com/open62541/open62541 и обёртки для с++ https://github.com/open62541pp/open62541pp

При старте запускается OPC UA сервер, реализующий возможность получать данные по протоколу OPC UA. В отдельном потоке происходит обновление данных из SharedMemory (SM). По умолчанию все датчики доступны для чтения, но при конфигурировании процесса можно указать датчики которые будут доступны на запись через функции OPC UA. Процесс может работать напрямую с SM через указатель или как отдельно запускаемый процесс работающий с SM через uniset RPC (remote call procedure).

Настройка OPCUAServer

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

<OPCUAServer name="OPCUAServer" port="4840" host="0.0.0.0"
appName="uniset2 OPC UA Server"
maxSubscriptions="10"
maxSessions="10"
updatePause="200"
namePrefix="uniset."
/>

К основным параметрам относятся

  • updatePause - мсек, период с которым обновляются значения датчиков
  • port - port на котором слушает OPC UA сервер
  • host - адрес на котором запускается сервер. По умолчанию 0.0.0.0

К дополнительным:

  • browseName - имя видимое в списке доступных. По умолчанию name узла
  • description - описание узла. По умолчанию будет взято browseName
  • appName - По умолчанию 'Uniset2 OPC UA Server'
  • appUri - По умолчанию 'urn:uniset2.server'
  • productUri - По умолчанию 'https://github.com/Etersoft/uniset2/'
  • namePrefix - Префикс добавляемый к названиям переменных.
  • maxSessions - Максимальное количество подключений
  • maxSecureChannels - максимальное количество https-подключений
  • maxSessionTimeout - мсек, Таймаут для сессий. По умолчанию 5 сек.
  • maxSecurityTokenLifetime - мсек, таймаут для токена
  • maxSubscriptions

Остальные параметры определяют детали функционирования OPC UA сервера https://www.open62541.org/doc/master/server.html#limits

См. так же help uniset2-opcua-server -h

Конфигурирование списка доступных переменных (variables) для OPC UA

Конфигурационные параметры задаются в секции <sensors> конфигурационного файла. Список обрабатываемых регистров задаётся при помощи двух параметров командной строки

  • --xxx-filter-field - задаёт фильтрующее поле для датчиков
  • --xxx-filter-value - задаёт значение фильтрующего поля. Необязательный параметр.
  • --xxx-filter-value-re - задаёт значение фильтрующего поля, в виде регулярного выражения. Необязательный параметр.

Пример конфигурационных параметров для запуска с параметрами --opcua-s-filter-field opcua --opcua-s-filter-value 1

Пример с регулярным выражением --opcua-s-filter-field opcua --opcua-s-filter-value-re "1|2"

<sensors name="Sensors">
...
<item name="MySensor_S" textname="my sesnsor" iotype="DI" opcua="1" opcua_rwmode="w"/>
<item name="OPCUA_Command_C" textname="opc ua command" iotype="DI" opc_ua="1" opcua_rwmode="w"/>
<item name="MySensor2_S" textname="my sesnsor" iotype="DI" opcua="1" opcua_name="Attribute2" opcua_displayname="Attr2"/>
...
</sensors>
  • opcua_rwmode - Режим доступа к датчику.
    • w - датчик будет доступен на запись через OPC UA.
    • none - не предоставлять доступ к датчику (не будет виден через OPC UA)
  • opcua_name - Имя OPC UA переменной, если не задано, то используется name (см. так же namePrefix)
  • opcua_displayname - Отображаемое имя. По умолчанию берётся name
  • opcua_displayname_lang - Язык для отображаемого имени. По умолчанию "en".
  • opcua_description - Описание. По умолчанию берётся textname
  • opcua_description_lang - Язык описания. По умолчанию "ru"
  • opcua_type - Тип переменной. Поддерживаются: bool, int32, float. Если не задан, тип определяется по типу датчика. DI,DO - bool, AI,AO - int32
  • opcua_mask - "битовая маска"(uint32_t). Позволяет задать маску для значения. Действует как на читаемые так и на записываемые переменные.
  • precision - точность, для преобразования числа в целое. Используется только для типа float. Задаёт степень 10. precision="2" означает 10^2 = 100. precision="3" означает 10^3 = 1000. При преобразовании AI датчиков используется округление.
  • opcua_method - Флаг означающий, что датчик привязан к OPCUA методу. OPCUA метод вызывается клиентом с аргументом, тип которого зависит от типа датчика. В данной реализации поддерживается три типа: boolean для DI, INT32 для AI и float для AI с precision. После вызова метода клиентом на сервере происходит выставление значения датчика вне цикла обновления SM т.е. принудительно. Проверка аргумента перед вызовом метода(см. open62541/server/ua_service_method.c) реализована путем сверки типов аргумента в запросе и в вызываемом методе. Если типы не совпадают, то вызов метода отклоняется сервером OPCUA с кодом ошибки UA_STATUSCODE_BADINVALIDARGUMENT и обработчик UA_setValueMethod не вызывается. Таким образом корректность типов проверяется на уровне libopen62541 перед вызовом обработчика, заданного при конфигурировании MethodNode в uniset2. Также в самом обработчике UA_setValueMethod тип аргумента сверяется с указанными ранее, а аргументы другого типа отклоняются с выставлением кода ошибки UA_STATUSCODE_BADINVALIDARGUMENT. Если же будет вызван обработчик с неизвестным methodID т.е. не будет совпадать ни с одним из сконфигурированных MethodNode в uniset2, то также обработка запроса отклоняется с кодом ошибки UA_STATUSCODE_BADMETHODINVALID.

По умолчанию все датчики доступны только на чтение.

Структура OPC UA узла

При запуске в дереве объектов создаётся специальный корневой объект "uniset", внутри которого регистрируются остальные доступные для работы объекты. В частности каждый uniset-узел регистрирует свои датчики в конкретном разделе заданном в теге opcua_folder="folder1.subfolder1", например. Каталоги разделяются точкой и корневой считается "имя_узла", от которого начинается путь каталога для каждого датчика. "uniset/имя_узла/folder1/subfolder1/xxx". Структура каталогов задается в общей секции OPCUA сервера в подсекции <folders>, например:

<OPCUAServer ...>
    <folders>
        <folder name="folder1" description="some sensors">
            <folder name="subfolder1" description="some sensors"/>
        </folder>
        <folder name="folder2" description="some sensors">
            <folder name="subfolder2" description="some sensors"/>
        </folder>
    </folders>
</OPCUAServer>

Если путь каталога в теге opcua_folder будет не соответсвовать каталогу в структуре(или просто ошибка в тексте), то будет генерироваться исключение и запуск остановится с ошибкой.

На рисунке представлен пример иерархии объектов