2. OPC UA核心概念精讲

OPC UA 之所以能成为跨厂商、跨平台的设备信息建模标准,根本原因在于它没有把“数据”简单当作一串地址,而是把设备抽象成一套可浏览、可查询、可调用的信息模型。理解这套模型,关键要抓住八个概念:地址空间、节点、引用、属性、变量、对象、方法、事件。它们不是并列的八个名词,而是层层嵌套、互相支撑的一套结构。

地址空间:设备信息的“总目录”

地址空间(AddressSpace)是 OPC UA 服务器对外暴露的全部信息集合。客户端连接服务器后,并不是直接去读某个寄存器,而是先进入地址空间,从根节点开始逐层浏览。地址空间由节点和节点之间的引用共同构成,本质上是一张有向图,而不是一棵严格的树——虽然实际建模中绝大多数关系表现为层次结构。

地址空间有一个约定俗成的入口:Root 文件夹。它下面通常挂三个子文件夹:Objects、Types、Views。Objects 存放设备实例,Types 存放类型定义,Views 存放按特定用途裁剪出的视图。客户端浏览设备时,一般从 Objects 进入。

节点:地址空间的最小单元

节点(Node)是地址空间的基本组成单位,每个节点由一个全局唯一的 NodeId 标识。NodeId 通常由命名空间索引、标识符类型和标识符值三部分组成,例如 ns=2;s=Machine1.Temperature。命名空间索引用于区分不同厂商或不同来源的标识符,避免冲突。

节点本身只是一个“壳”,它承载什么语义,取决于它拥有哪些属性、引用以及它属于哪个节点类。OPC UA 定义了八种基本节点类:对象、变量、方法、对象类型、变量类型、引用类型、数据类型、视图。本节重点讨论其中与设备建模最直接相关的对象、变量、方法和事件。

属性:节点的固有描述

属性(Attribute)是节点自带的、用于描述节点自身的数据。每个节点都至少拥有 NodeId、BrowseName、DisplayName、NodeClass 等基础属性。变量节点还会额外拥有 Value、DataType、ValueRank、AccessLevel 等属性。

需要特别区分“属性”和“变量”:属性是节点元数据,不能被子节点继承,也不能被客户端随意新增;变量是建模出来的数据点,可以挂在对象下面,可以带类型定义。例如一个温度变量节点,它的 Value 是属性,而这个变量节点本身挂在某个对象下,才是建模意义上的“变量”。

引用:把节点连成模型

引用(Reference)描述节点之间的关系,是地址空间从“一堆节点”变成“一张模型图”的关键。引用是有方向的,分为正向引用和反向引用。常见的引用类型包括:Organizes(组织关系)、HasComponent(组合关系)、HasProperty(属性关系)、HasTypeDefinition(类型定义关系)、HasSubtype(子类型关系)。

以一台电机为例:Objects 通过 Organizes 指向 Motor1 对象;Motor1 通过 HasComponent 指向 Temperature 变量;Temperature 通过 HasTypeDefinition 指向 BaseDataVariableType。这三条引用共同确定了“电机有一个温度变量”这一语义。

对象与变量:设备建模的主角

对象(Object)代表现实世界中的实体,如一台机床、一个工位、一个传感器。变量(Variable)代表对象上可读写或可观测的数据,如温度值、运行状态、报警码。对象通过 HasComponent 引用变量,形成“对象—变量”的从属结构。

变量分为两类:数据变量(DataVariable)和属性变量(Property)。数据变量通常表示过程数据,属性变量通常表示配置参数或描述信息。变量还可以是数组,通过 ValueRank 描述维度,例如 ValueRank=1 表示一维数组。

方法:让信息模型可被调用

方法(Method)是挂在对象上的可执行操作,客户端可以通过 Call 服务调用它。方法有输入参数和输出参数,参数本身也是变量节点,通过 HasProperty 或 HasComponent 挂在方法节点下。例如 Motor1 对象下可以有一个 Start 方法,输入参数为 RampTime,输出参数为 Result。方法让信息模型不仅能“看”,还能“控”。

事件:让信息模型能主动通知

事件(Event)是服务器主动向客户端推送的通知,用于表达状态变化、报警、操作记录等。事件不是节点,而是一种通知机制。客户端通过 CreateSubscription 建立订阅,再通过 MonitoredItem 指定要监听的事件源。事件类型通过 EventType 定义,常见的有 BaseEventType、AlarmConditionType 等。事件让信息模型从“被动查询”升级为“主动上报”。

OPC UA 地址空间与设备信息模型结构 Root Objects Types Views Organizes Organizes Organizes Motor1 Object Organizes Temperature Variable Speed Variable HasComponent HasComponent Start() Method HasComponent OverheatEvent EventType GeneratesEvent BaseDataVariableType VariableType HasTypeDefinition 节点属性示例(Temperature 变量节点) NodeId BrowseName Value DataType AccessLevel ValueRank 属性描述节点自身;变量描述设备数据;引用描述节点关系;方法提供调用;事件提供通知。

八个概念如何协同构成设备信息模型

把上述概念串起来看:地址空间是容器,节点是单元,引用是连接线,属性是节点自带的描述,变量和对象是设备建模的主要节点类,方法提供可调用能力,事件提供主动通知能力。一个完整的设备信息模型,就是在这套机制上,把一台真实设备的结构、数据、操作和状态变化,映射成客户端可浏览、可读写、可调用、可订阅的节点图。

以一台电机为例,建模过程大致如下:在 Objects 下创建 Motor1 对象节点,类型定义为 MotorType;在 Motor1 下创建 Temperature、Speed 两个变量节点,类型定义为 BaseDataVariableType,并设置 DataType=Double、AccessLevel=CurrentRead;在 Motor1 下创建 Start 方法节点,输入参数 RampTime 为 Duration 类型;在 Motor1 上挂接 OverheatEvent 事件类型,当温度超过阈值时由服务器触发事件。客户端连接后,从 Root 浏览到 Motor1,读取 Temperature 的 Value,调用 Start 方法,订阅 OverheatEvent,整个交互过程都建立在节点、引用、属性、变量、对象、方法和事件这八个概念之上。

理解这八个概念时,建议始终问三个问题:这个节点是什么类?它通过什么引用挂在谁下面?它有哪些属性和子节点?把这三个问题回答清楚,设备信息模型的结构就清晰了。

建模时的常见误区

第一个误区是把属性当变量用。属性是节点元数据,客户端不能像读写变量那样随意写属性;需要暴露给客户端读写的数据,应该建成变量节点。第二个误区是忽略 HasTypeDefinition 引用。没有类型定义的变量节点虽然也能读值,但客户端无法判断它的语义和数据类型,互操作性会大打折扣。第三个误区是引用方向混乱。正向引用和反向引用必须成对出现,建模时只建正向引用、不建反向引用,会导致客户端从子节点向上浏览时找不到父节点。