2. OPC UA基础概念

学习 OPC UA 客户端与服务端开发,第一步不是急着写连接代码,而是先建立一套“信息模型”的思维框架。OPC UA 与传统 OPC 最大的区别,在于它不再只是搬运数值,而是把设备、参数、状态、方法都抽象成一套可浏览、可寻址、可扩展的地址空间(AddressSpace)。客户端看到的不是一堆零散标签,而是一棵有层级、有语义、有类型约束的节点树。理解这套术语,是后续读写、订阅、方法调用和自定义信息模型的基础。

一、地址空间:服务端对外暴露的“信息地图”

地址空间是 OPC UA 服务端中所有节点及其引用构成的集合,可以把它理解成服务端对外公开的一棵“信息地图”。客户端通过 Browse 服务逐层浏览,通过 Read/Write 服务访问节点值,通过 Call 服务调用方法。地址空间不是简单的文件夹树,而是一张有向图:节点之间通过引用连接,同一个节点可以被多个父节点引用,也可以被多个视图筛选呈现。

地址空间通常由标准命名空间(如 http://opcfoundation.org/UA/)和厂商自定义命名空间组成。标准命名空间定义了 ObjectTypes、VariableTypes、DataTypes、ReferenceTypes 等基础类型;厂商命名空间则承载具体设备模型。命名空间索引(NamespaceIndex)是节点 ID 的重要组成部分,开发中必须区分清楚。

二、节点、属性与引用:地址空间的三块基石

节点(Node)是地址空间的最小寻址单位,每个节点由 NodeId 唯一标识,例如 ns=2;s=Device1.Temperature。NodeId 包含命名空间索引和标识符,标识符可以是数值、字符串、GUID 或字节串。节点本身不直接“存值”,它通过属性承载元数据,通过引用连接其他节点。

属性(Attribute)是节点的固有特征,每个节点都有一组标准属性,如 NodeId、NodeClass、BrowseName、DisplayName、Description、WriteMask、UserWriteMask 等。变量节点还额外拥有 Value、DataType、ValueRank、AccessLevel、Historizing 等属性。属性不是引用,不能被浏览成子节点,只能通过 Read/Write 服务按 AttributeId 访问。

引用(Reference)描述节点之间的关系,是有向的。常见引用类型包括 Organizes、HasComponent、HasProperty、HasTypeDefinition、HasSubtype、HasEventSource 等。引用让地址空间形成层次和语义:Organizes 表示组织关系,HasComponent 表示组成关系,HasTypeDefinition 指向类型定义。客户端浏览时,正是沿着引用从一个节点走到另一个节点。

OPC UA 地址空间核心术语关系 AddressSpace 地址空间(节点+引用集合) Node 节点(NodeId 唯一标识) Reference 引用(有向关系) 包含 通过引用连接 Attribute 属性(NodeId/Value 等) Variable 变量(可读写值) Method 方法(可调用) 拥有 NodeClass 之一 NodeClass 之一 Object 对象(设备/模块实例) View 视图(筛选后的子集) ObjectType 对象类型(模板定义) NodeClass 之一 NodeClass 之一 NodeClass 之一 典型引用关系 Organizes · HasComponent · HasProperty · HasTypeDefinition · HasSubtype 客户端沿引用 Browse,按 NodeId 定位,按 AttributeId 读写

三、变量、方法、对象与视图:节点类的具体形态

OPC UA 用 NodeClass 区分节点的种类,常见的有 Object、Variable、Method、ObjectType、VariableType、ReferenceType、DataType、View 八类。开发中最常打交道的是前四种:

  • 对象(Object):表示设备、模块、系统等实体,本身不存值,通过 HasComponent 或 HasProperty 挂载变量和方法。例如 Device1 是一个对象,其下挂 Temperature 变量和 Start 方法。
  • 变量(Variable):承载具体数据值,拥有 Value、DataType、ValueRank、AccessLevel 等属性。变量可以是标量、数组或矩阵,AccessLevel 决定客户端能否读写。
  • 方法(Method):表示可被客户端调用的操作,拥有 InputArguments 和 OutputArguments 属性描述参数。方法调用通过 Call 服务完成,可带会话和用户权限校验。
  • 视图(View):是地址空间的子集投影,用于按业务视角筛选节点。视图本身也是节点,客户端可以指定 View 进行 Browse,只看到与该视图相关的节点和引用。

对象与变量之间通过 HasComponent 连接,对象与对象类型之间通过 HasTypeDefinition 连接。类型节点(ObjectType、VariableType)定义模板,实例节点继承其结构。这种“类型—实例”分离的设计,使服务端可以批量建模,客户端也能按类型做通用处理。

四、核心术语速查清单

术语 英文 作用 典型示例
地址空间 AddressSpace 服务端所有节点与引用的集合 整棵信息模型树
节点 Node 最小寻址单位,由 NodeId 标识 ns=2;s=Device1
属性 Attribute 节点的固有元数据 BrowseName、Value、DataType
引用 Reference 节点之间的有向关系 HasComponent、Organizes
变量 Variable 承载可读写数据值 Temperature = 25.6
方法 Method 可被客户端调用的操作 Start()、Stop()
对象 Object 设备或模块实例 Device1、Line1
视图 View 地址空间的筛选子集 OperatorView、MaintenanceView

五、案例:从客户端视角看一次温度读取

假设服务端建模如下:Device1 是 Object,其下通过 HasComponent 挂载 Temperature Variable,该变量 HasTypeDefinition 指向 AnalogItemType,DataType 为 Double,AccessLevel 为 Read。客户端读取流程可以简化为:

1. 建立 Session,获取 NamespaceTable
2. Browse(Device1) → 返回 Temperature 节点引用
3. Read(ns=2;s=Device1.Temperature, AttributeId=Value)
4. 服务端返回 DataValue:25.6,StatusCode=Good
5. 若需订阅,则创建 MonitoredItem 监听该节点 Value 变化

这个过程中,客户端并不关心底层是 PLC 还是网关,它只认 NodeId、AttributeId 和引用关系。这正是 OPC UA 信息模型的价值:把设备语义标准化,让客户端代码可以通用化。

开发提示:自定义命名空间时,建议把设备层级、变量命名、类型定义一次性规划好。NodeId 一旦对外发布,后续变更会影响所有客户端,应尽量保持稳定。

六、常见误区与复盘

  • 误区一:把属性当子节点浏览。属性不是引用目标,Browse 看不到 Value 属性,必须用 Read 按 AttributeId 读取。
  • 误区二:忽略 NodeId 的命名空间索引。同一个字符串标识符在不同命名空间下是不同的节点,跨服务端迁移时尤其要注意。
  • 误区三:认为对象一定存值。对象只是容器,值在变量上;方法也不存值,它描述可执行操作。
  • 误区四:视图等于权限。视图只是浏览筛选,不等于访问控制;真正的权限由 Session、UserIdentity 和 AccessLevel 共同决定。

复盘来看,地址空间、节点、引用、属性、变量、方法、对象、视图这八个术语并不是孤立概念,而是一套层层递进的信息模型:地址空间是容器,节点是单元,属性是描述,引用是关系,变量和方法是行为与数据的载体,对象是实例,视图是视角。把这套关系理顺,后续的读写服务、订阅服务、方法调用和自定义信息模型开发都会顺畅很多。