3. 设备信息模型基础

在 OPC UA 中,一台真实设备并不会以“设备”这个整体直接暴露给客户端,而是被拆解为一棵由节点组成的地址空间子树。理解“设备→节点→对象→变量→方法”的映射方法,是后续做数据采集、建模复用和客户端浏览的基础。本节先讲清映射关系,再给出建模原则与几种常见模式。

一、从物理设备到地址空间:四层映射

OPC UA 的地址空间由节点(Node)构成,每个节点有唯一的 NodeId,并带有 NodeClass 属性。NodeClass 决定了这个节点“是什么”,常见的有 Object、Variable、Method、ObjectType、VariableType、DataType、ReferenceType、View 八类。设备建模时最常用的是前三种:

  • 对象(Object):表示一个实体或实体的组成部分,如“1号反应釜”“温度传感器A”。对象本身不携带过程值,它靠引用把变量、方法、子对象组织起来。
  • 变量(Variable):承载数据值,如“当前温度=78.5 ℃”。变量有 Value、DataType、ValueRank、AccessLevel 等属性,是数据采集真正读取的对象。
  • 方法(Method):表示可被客户端调用的操作,如“启动”“标定”“复位”。方法有输入参数和输出参数,调用时通过 Call 服务执行。

把一台设备映射进地址空间,通常按下面的层次展开:设备整体对应一个顶层 Object;设备的每个可测点、可设参数对应一个 Variable;设备可执行的动作对应 Method;设备内部的子部件(如一台泵的电机、变频器)再对应子 Object。这样,客户端从顶层对象出发,沿引用逐级浏览,就能定位到任意一个变量或方法。

物理设备 1号反应釜 温度/压力/搅拌/进料阀 顶层 Object Reactor_01 NodeId: ns=2;s=Reactor_01 子 Object Agitator(搅拌器) Motor / Gearbox 映射 HasComponent Variable Temperature Double / ℃ / 只读 Variable Setpoint Double / ℃ / 读写 Method Start / Stop Call 服务调用 HasProperty HasProperty HasComponent 关键引用类型(决定浏览路径) HasComponent:对象→子对象/变量,构成“组成部分”关系 HasProperty:对象→属性变量,如工程单位、量程、描述 HasTypeDefinition:实例→类型定义,决定该实例具备哪些标准成员 Organizes:文件夹式组织,仅用于分组,不表示物理组成

二、建模原则:先定类型,再落实例

直接给每个设备手工建节点,短期可行,长期会失控。OPC UA 的推荐做法是类型驱动建模:先用 ObjectType 定义“这类设备长什么样”,再用实例化生成具体设备。核心原则有四条。

原则一:类型定义成员,实例只填值。例如定义 ReactorType,在类型里声明 Temperature、Pressure、Setpoint 三个变量和 Start、Stop 两个方法。现场有 8 台反应釜时,只需实例化 8 次,每台自动获得同样的成员结构。这样客户端只需认识一种类型,就能浏览所有同类设备。

原则二:用标准类型优先。OPC UA 已为大量设备定义了标准类型,如 BaseObjectType、FolderType、AnalogItemType、DataItemType。变量应尽量选用 AnalogItemType 或 DataItemType 作为 TypeDefinition,而不是裸的 BaseDataVariableType,因为前者自带 EURange、EngineeringUnits 等属性,客户端能直接读出量程和单位。

原则三:NodeId 稳定且可读。NodeId 是采集配置的锚点,一旦发布就不应随意变更。推荐使用字符串型 NodeId,如 ns=2;s=Reactor_01.Temperature,把设备名和测点名编进标识符,便于人工排查;避免使用纯数字自增 ID,否则设备重启或重新导入后容易错位。

原则四:区分“组成”与“组织”。物理上属于设备的部件用 HasComponent;仅为了分类归档(如把所有温度变量放进一个文件夹)用 Organizes。混用会导致客户端浏览树与设备实际结构不一致。

建模时先问三个问题:这台设备由哪些部件组成?每个部件有哪些可读可写的数据?设备能执行哪些动作?答案分别对应子对象、变量、方法,映射关系就清晰了。

三、常见建模模式

模式一:设备-部件-测点三级树。适合结构清晰的成套设备。顶层是设备对象,第二层是部件对象(电机、阀门、传感器),第三层是变量。采集时按“设备.部件.测点”路径定位,例如 Reactor_01.Agitator.Motor.Speed。

模式二:扁平测点 + 类型复用。适合测点数量大、结构简单的场景,如一块采集模块的 32 路通道。每个通道实例化同一个 AnalogChannelType,只改 NodeId 和工程单位,浏览树浅、配置快。

模式三:方法封装动作。把“启动”“停止”“标定”等操作建模为 Method,输入参数用 Argument 描述。客户端调用时传入参数,服务端执行后返回输出参数。这样采集系统不仅能读数据,还能下发控制,但要注意方法调用需要会话与权限支持。

下面给出一份可直接参考的建模映射表,用于把一台反应釜的物理对象落到地址空间:

物理对象NodeClassBrowseNameNodeId 示例DataType / 说明
1号反应釜ObjectReactor_01ns=2;s=Reactor_01TypeDefinition: ReactorType
温度测点VariableTemperaturens=2;s=Reactor_01.TemperatureDouble,℃
温度设定值VariableSetpointns=2;s=Reactor_01.SetpointDouble,℃
搅拌器ObjectAgitatorns=2;s=Reactor_01.AgitatorHasComponent
搅拌转速VariableSpeedns=2;s=Reactor_01.Agitator.SpeedDouble,rpm
启动动作MethodStartns=2;s=Reactor_01.Start无输入,返回 Boolean

建模完成后,用 UaExpert 或自研客户端从顶层对象浏览,应能看到 Temperature、Setpoint、Agitator、Start 四个成员;点开 Agitator 应看到 Speed。若浏览树与上表一致,说明映射正确;若出现成员缺失或层级错位,通常是 TypeDefinition 未正确设置或引用类型用错。采集端配置时,直接以 NodeId 为键建立测点表,即可把 OPC UA 变量与上位机数据库字段一一对应。