3、OPC UA 信息模型:对象、变量、方法、类型层次结构与实例化

OPC UA 信息模型是其区别于传统工业通信协议(如 Modbus、Profibus)的核心特征。它不仅仅传输原始数据点,而是将工业现场的设备、传感器、控制器及其相互关系,以面向对象的方式在地址空间中建模。这种模型使得客户端能够自描述地发现和理解服务器的数据结构,无需预先定义变量表。

3.1 信息模型的核心要素

OPC UA 信息模型由四种基本节点构成,它们共同描述了工业自动化系统中的实体与行为:

节点类型 图标(概念) 描述 工业示例
对象 (Object) 📦 代表物理或逻辑实体,可包含变量、方法和其他对象。是信息模型的“容器”。 一台变频器、一个温度传感器、一个控制回路
变量 (Variable) 📊 代表数值或状态,具有数据类型(如 Float、Boolean、String)。是数据采集的直接目标。 电机转速 (RPM)、阀门开度 (%)、设备运行状态 (Running/Stopped)
方法 (Method) ⚙️ 代表可被客户端调用的函数或操作,支持输入/输出参数。用于执行控制指令。 复位报警、启动电机、切换配方
引用 (Reference) 🔗 连接两个节点,描述它们之间的关系(如包含、类型定义、层次结构)。 “电机”对象包含“转速”变量;“温度传感器”是“传感器”类型的实例
关键概念: 在 OPC UA 地址空间中,一切皆节点 (Node)。每个节点通过 NodeId 唯一标识,通过 BrowseName 提供可读名称。信息模型的核心工作就是定义这些节点及其引用关系。

3.2 类型层次结构与实例化

OPC UA 采用严格的面向对象类型系统。所有对象和变量都是某个类型的实例。类型本身也是对象,存储在地址空间中,可以被浏览和发现。这种机制实现了模型的复用和标准化。

3.2.1 类型层次结构

类型系统分为三个主要层次:

  • 基础类型 (Base Types):由 OPC UA 规范定义,是所有类型的根。例如 BaseObjectType、BaseVariableType、BaseDataType。
  • 标准类型 (Standard Types):由 OPC 基金会或行业组织(如 PLCopen、MDIS)定义,用于特定领域。例如 FolderType、PropertyType、AnalogItemType。
  • 自定义类型 (Custom Types):由设备制造商或系统集成商根据实际设备定义,继承自标准类型或基础类型。例如 MyCompany_PumpType、Custom_DriveType。
最佳实践: 在构建信息模型时,应优先继承现有的标准类型(如 AnalogItemType 用于模拟量,TwoStateDiscreteType 用于开关量),仅在必要时才创建全新的自定义类型。这保证了互操作性。

3.2.2 实例化过程

实例化是指根据类型定义创建具体对象或变量的过程。一个类型定义了其子节点的结构(即包含哪些变量、方法、对象),实例化时,这些子节点会被自动创建。

// 伪代码:根据 PumpType 实例化一个具体的泵对象
// 1. 定义类型 PumpType (继承自 BaseObjectType)
//    - 包含变量: Speed (Float), Pressure (Float)
//    - 包含方法: Start(), Stop()

// 2. 实例化: 在地址空间中创建对象 "Pump_01"
//    - NodeId: ns=2;i=1001
//    - TypeDefinition: PumpType
//    - 自动生成子节点:
//      - Pump_01.Speed (Float)
//      - Pump_01.Pressure (Float)
//      - Pump_01.Start (Method)
//      - Pump_01.Stop (Method)
注意: 实例化时,子节点是“复制”类型定义的结构,但每个实例拥有自己独立的值空间。修改类型定义的结构(如添加新变量)不会自动影响已创建的实例,除非使用特定的建模规则(如模型变更事件)。

3.3 信息模型结构图

下图展示了一个简化的工业泵站信息模型,说明了对象、变量、方法以及类型层次结构之间的关系。

OPC UA 信息模型结构示例:泵站 OPC UA 信息模型结构示例:泵站 类型层次结构 (Type Hierarchy) BaseObjectType (基础对象类型) PumpType (标准泵类型) MyCompany_HighPressurePumpType 实例化 (Instantiation) 对象: Pump_01 (类型: PumpType) 变量: Speed 变量: Pressure 方法: Start() 方法: Stop() HasTypeDefinition 说明:类型定义结构(包含哪些子节点),实例化时复制结构并分配独立的值空间。 引用 "HasTypeDefinition" 将实例指向其类型定义。

3.4 对象与变量的属性

除了基本的值,OPC UA 节点还携带丰富的元数据(属性),这些属性对于数据采集和客户端解析至关重要。

属性名 适用节点 描述 工业意义
NodeId 所有节点 节点在地址空间中的唯一标识符 客户端通过 NodeId 直接读取或订阅变量
BrowseName 所有节点 用于浏览层次结构的非本地化名称 通常与变量名一致,便于人机界面显示
DisplayName 所有节点 支持多语言的本地化显示名称 中文操作界面显示“电机转速”,英文显示“Motor Speed”
Value 变量 当前值 实时采集的 1450 RPM
DataType 变量 值的数据类型(如 Float、Int16、Boolean) 决定如何解析字节流,避免类型转换错误
AccessLevel 变量 访问权限(读、写、读写) 防止误写入只读的工艺参数
MinimumSamplingInterval 变量 最小采样间隔(毫秒) 告诉客户端不要以高于此频率轮询,避免 CPU 过载
Executable 方法 指示方法当前是否可执行 设备处于安全状态时,禁止调用“启动”方法

3.5 方法调用机制

方法是 OPC UA 实现控制下行的重要途径。与读/写变量不同,方法调用是同步或异步执行一段服务器端的逻辑。

3.5.1 方法的结构

  • InputArguments:一个属性,定义了方法所需的输入参数列表(名称、数据类型、描述)。
  • OutputArguments:一个属性,定义了方法执行后的输出参数列表。
  • Executable / UserExecutable:指示方法是否可执行,以及当前用户是否有权限执行。

3.5.2 调用流程

  1. 客户端通过 Browse 发现方法节点。
  2. 客户端读取 InputArguments 属性,了解需要传递哪些参数。
  3. 客户端调用 Call 服务,传入目标 NodeId 和参数值。
  4. 服务器执行方法逻辑(如启动电机、复位报警)。
  5. 服务器返回 OutputArguments(如操作结果、状态码)。
// 示例:调用复位报警方法
// 方法 NodeId: ns=2;i=2001
// 输入参数: AlarmCode (UInt32)
// 输出参数: ResetResult (Boolean), Message (String)

// 客户端请求 (伪代码)
CallRequest {
  ObjectId: ns=2;i=1001  // 所属对象
  MethodId: ns=2;i=2001  // 方法
  InputArguments: [1234] // 报警代码
}

// 服务器响应 (伪代码)
CallResponse {
  OutputArguments: [true, "报警 1234 已复位"]
}
安全提示: 方法调用通常涉及设备控制,OPC UA 服务器应严格校验 UserExecutable 属性。建议对关键方法(如写参数、启停设备)启用会话加密和用户认证,防止未授权操作。

3.6 信息模型的浏览与发现

信息模型的强大之处在于客户端可以在运行时动态发现服务器的结构,无需预先配置。这通过 Browse 服务实现。

  • Browse 服务:客户端从一个起始节点(通常是 Root 节点)开始,遍历其所有引用关系,发现子节点。
  • BrowsePath:客户端可以通过一系列相对路径(如 /Objects/Server/ServerStatus)快速定位节点。
  • 语义标签 (Semantic Tags):现代 OPC UA 规范支持为变量添加语义标签(如 @Temperature、@Pressure),使得客户端能够理解数据的含义,而不仅仅是名称。
实战要点: 在配置 OPC UA 客户端时,不要硬编码 NodeId。优先使用 Browse 服务动态发现节点,或使用 别名 (Alias) 机制。这样当服务器信息模型版本更新时,客户端无需修改代码即可适配。