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 等。事件让信息模型从“被动查询”升级为“主动上报”。
八个概念如何协同构成设备信息模型
把上述概念串起来看:地址空间是容器,节点是单元,引用是连接线,属性是节点自带的描述,变量和对象是设备建模的主要节点类,方法提供可调用能力,事件提供主动通知能力。一个完整的设备信息模型,就是在这套机制上,把一台真实设备的结构、数据、操作和状态变化,映射成客户端可浏览、可读写、可调用、可订阅的节点图。
以一台电机为例,建模过程大致如下:在 Objects 下创建 Motor1 对象节点,类型定义为 MotorType;在 Motor1 下创建 Temperature、Speed 两个变量节点,类型定义为 BaseDataVariableType,并设置 DataType=Double、AccessLevel=CurrentRead;在 Motor1 下创建 Start 方法节点,输入参数 RampTime 为 Duration 类型;在 Motor1 上挂接 OverheatEvent 事件类型,当温度超过阈值时由服务器触发事件。客户端连接后,从 Root 浏览到 Motor1,读取 Temperature 的 Value,调用 Start 方法,订阅 OverheatEvent,整个交互过程都建立在节点、引用、属性、变量、对象、方法和事件这八个概念之上。
建模时的常见误区
第一个误区是把属性当变量用。属性是节点元数据,客户端不能像读写变量那样随意写属性;需要暴露给客户端读写的数据,应该建成变量节点。第二个误区是忽略 HasTypeDefinition 引用。没有类型定义的变量节点虽然也能读值,但客户端无法判断它的语义和数据类型,互操作性会大打折扣。第三个误区是引用方向混乱。正向引用和反向引用必须成对出现,建模时只建正向引用、不建反向引用,会导致客户端从子节点向上浏览时找不到父节点。