Заметки по OPC UA
OPC UA FAQ - ответы на частые вопросы
Термин OPC UA - идентификатор узла NodeId
NodeId в OPC UA — это уникальный идентификатор, назначаемый каждому узлу (переменным, методам, объектам) в адресном пространстве сервера OPC UA. Этот идентификатор позволяет клиентам напрямую обращаться к узлу, делая возможными операции чтения, записи и вызова методов.
NodeId состоит из двух частей:
Индекс пространства имён (ns).
Это целое число, представляющее пространство имён, в котором находится узел.
Пространства имён помогают организовывать узлы и избегать конфликтов между
разными поставщиками или моделями.
Идентификатор (i, s, g, b).
Эта часть однозначно идентифицирует узел внутри пространства имён.
Идентификатор может быть числовым (i), строковым (s),
GUID (g) или непрозрачным (b).
Например, NodeId в виде ns=2;i=2022 означает,
что индекс пространства имён равен 2 (указывает на вторую запись в NamespaceArray),
а идентификатор — 2022 (числовой идентификатор).
Как избежать конфликтов между пространствами имён?
Чтобы избежать конфликтов между пространствами имён в OPC UA, можно следовать таким рекомендациям:
- Не изменять индексы таблицы пространств имён на сервере, а только добавлять записи, потому что клиент может кэшировать NodeId с помощью индексов.
- Использовать таблицу сопоставления URI и индексов для каждого контекста. У сервера своя таблица в NamespaceArray, а у каждой модели — своя, специфичная для конкретного файла NodeSet XML.
- При загрузке моделей использовать URI, а индексы — это оптимизация. Они позволяют не писать URI каждый раз или не передавать длинную строку через сетевое соединение.
- При желании установить конкретные индексы перед загрузкой модели с помощью метода UaServer.getNamespaceTable().
Если клиент не знает индекс пространства имён на конкретном сервере, он может запросить список пространств имён и таким образом определить правильный индекс для определённого имени пространства имён.
Как оптимизировать загрузку моделей в OPC UA?
Для оптимизации загрузки моделей в OPC UA можно предпринять следующие шаги:
- Ограничить количество запросов от клиентских приложений. Например, на сервере Kepware есть возможность контролировать скорость сканирования, что позволяет снижать использование ресурсов.
- Настроить режим подписки. Сервер будет отсылать клиенту только те теги, которые изменились. Это позволит разгрузить сеть от передачи повторяющихся неизменных значений.
- Использовать режим обновления данных. Клиент вызывает одновременное чтение всех активных тегов. Такое деление тегов уменьшает загрузку процессора обновлением данных, принимаемых из физического устройства.
- Варьировать параметры коммуникационного стека. Например, настроить размер очереди, через которую буферизируются данные, а потом публикуются сразу все накопленные в очереди данные.
Выбор оптимальных настроек зависит от конкретной ситуации и оборудования.
Как выбрать подходящий коммуникационный стек?
Выбор подходящего коммуникационного стека OPC UA зависит от конкретных задач и требований проекта.
Некоторые характеристики, которые стоит учесть:
- Многоплатформенная реализация. Доступны версии для ANSI C, Java и .NET.
- Масштабируемость. Стек подходит для работы с различными устройствами: от интеллектуальных датчиков и исполнительных механизмов до мэйнфреймов.
- Поддержка многопоточной и однопоточной/однозадачной работы. Это необходимо для переноса стека на встроенные устройства.
- Безопасность. Стандарт включает встроенные механизмы шифрования, аутентификации и авторизации.
- Настраиваемые тайм-ауты для каждой службы.
- Возможность фрагментации больших дейтаграмм.
Также стоит обратить внимание на то, какие языки программирования поддерживает стек: коммерческие SDK доступны для C, C++, Java и .NET, а стеки с открытым исходным кодом — для C, C++, Java, Javascript (node), Tcl и Python.
Для выбора подходящего коммуникационного стека рекомендуется обратиться к специалисту.
Как выбрать между коммерческими и открытыми SDK?
Выбор между коммерческими и открытыми SDK зависит от конкретных требований и задач проекта.
Некоторые факторы, которые стоит учесть:
- Стоимость. SDK с открытым исходным кодом бесплатны, но для их разработки необходимы специалисты или услуги компании-разработчика. Коммерческие SDK требуют оплаты лицензии на использование и расходов на интеграцию с приложением, но обеспечивают более быструю и квалифицированную поддержку, высокую безопасность и функциональность «из коробки».
- Простота использования. Коммерческие SDK обычно имеют продуманный API и обширную документацию, что упрощает разработку. Открытые SDK могут быть сложнее в использовании для новичков.
- Поддержка. Для SDK с открытым исходным кодом поддержка обычно ограничена онлайн-сообществами пользователей в виде форумов и блогов. У коммерческих продуктов часто есть команда поддержки клиентов, которая знакома с продуктом и может помочь при возникновении проблем.
- Стабильность. Коммерческие SDK обычно более стабильны, так как имеют продуманные дорожные карты продукта, которые определяют приоритеты разработки.
Таким образом, выбор в пользу того или иного типа SDK зависит от конкретных потребностей и предпочтений разработчика.
Как настроить NodeId для разных типов узлов?
Настройка NodeId для разных типов узлов в OPC UA включает использование атрибута NodeIdType, который указывает, какой тип OPC-UA используется для идентификатора.
- Для числового идентификатора можно использовать метод ua.NodeId(1,2)
- Для строкового идентификатора — метод ua.NodeId('Test',2)
- Для идентификатора в виде байтов — метод ua.NodeId(b'Test',2)
Также NodeId можно построить из одной строки, для этого используется метод ua.NodeId.from_string()
Входная строка должна быть в формате <key>=<val>;[<key>=<val>] — список пар ключ-значение, разделённых точками с запятой.
Кроме класса NodeId, существует класс ExpandedNodeId, который добавляет атрибуты NamespaceUri и ServerIndex, чтобы сделать ID уникальным для разных серверов и пространств имён.
Какие типы OPC-UA существуют?
Некоторые типы данных в OPC UA:
- Boolean. Значение «TRUE» или «FALSE».
- SByte. Однобайтовое целое число со знаком в диапазоне от −128 до 127 включительно.
- Byte. Однобайтовое беззнаковое целое число в диапазоне от 0 до 255 включительно.
- Int16. Двухбайтовое (16-битное) целое число со знаком в диапазоне от −32 768 до 32 767 включительно.
- UInt16. Двухбайтовое (16-битное) беззнаковое целое число в диапазоне от 0 до 65 535 включительно.
- Int32. Четырёхбайтовое (32-битное) целое число со знаком в диапазоне от −2 147 483 648 до 2 147 483 647 включительно.
- UInt32. Четырёхбайтовое (32-битное) беззнаковое целое число в диапазоне от 0 до 4 294 967 295 включительно.
- Int64. Восемьбайтовое (64-битное) целое число со знаком в диапазоне от −9 223 372 036 854 775 808 до 9 223 372 036 854 775 807 включительно.
- UInt64. Восемьбайтовое (64-битное) беззнаковое целое число в диапазоне от 0 до 18 446 744 073 709 551 615 включительно.
- Float. Четырёхбайтовое число с плавающей точкой.
- Double. Восьмибайтовое число с плавающей точкой двойной точности.
- String. Строка Unicode, которая должна исключать управляющие символы, не являющиеся пробелами.
- DateTime. Дата и время, представленные как 64-битное целое число со знаком, которое представляет число 100 наносекундных интервалов с 1 января 1601 года (UTC).
- Guid. 128-битный глобально уникальный идентификатор.
- ByteString. Последовательность байтовых значений с информацией о длине.
- XmlElement. Тип данных, используемый для транспортировки элементов XML.
- ExtensionObject. Используется для транспортировки структурных типов данных.