3. OPC UA信息模型与矿山设备建模

OPC UA 与早期 OPC Classic 最本质的差别,不在于传输协议从 COM/DCOM 换成了 TCP,而在于它把“数据”升级成了“信息”。在 OPC Classic 中,一个标签往往只是一个带名字的数值,比如 Tag_1023 = 45.6,上位机无法从名字本身判断这是哪台设备的什么量、单位是什么、是否可写、超限时该报警还是该停机。OPC UA 则要求每个节点都挂在一个有类型、有语义的地址空间里,客户端通过浏览(Browse)就能知道“这是一个球磨机的主轴承温度,单位摄氏度,只读,工程上限 85℃”。本节要做的,就是为矿山设备建立这样一套可复用、可浏览、可继承的信息模型。

一、信息模型的三个基本构件:对象、变量、方法

OPC UA 地址空间由节点(Node)构成,建模时最常用的是对象(Object)、变量(Variable)、方法(Method)三类,外加事件(Event)作为对象向外发布的通告。它们的关系可以这样理解:对象是设备的“壳”,变量是设备的状态与参数,方法是设备可被调用的动作,事件是设备主动上报的“发生了什么”。

以矿山选厂的球磨机为例,一个 BallMill 对象下通常挂载:运行状态、主轴承温度、电机电流、给矿量、筒体转速等变量;启动、停止、复位急停等方法;以及过载、轴承超温、润滑失效等事件。变量本身还带有 DataType、ValueRank、AccessLevel、EngineeringUnits、EURange 等属性,这些属性正是 SCADA 侧自动生成量程、单位、读写权限的依据。方法则通过 InputArguments 与 OutputArguments 两个属性描述签名,客户端调用前可先读取签名,避免参数错配。

二、用类型(ObjectType)实现“一次建模、多台复用”

矿山现场同一型号设备往往成批出现:一个选厂可能有 4 台球磨机、12 台渣浆泵、30 条皮带机。如果逐台手工建节点,工作量巨大且极易不一致。正确做法是先定义设备类型(ObjectType),再由类型实例化出具体设备对象(Object),实例自动继承类型下所有变量、方法和事件。这就是“可复用设备类型”的含义。

建模时通常采用分层继承:先建一个抽象的 MineEquipmentType,统一定义所有矿山设备共有的 DeviceID、RunState、FaultCode、Location 等变量和 Reset 方法;再派生 BallMillType、SlurryPumpType、BeltConveyorType 等具体类型,各自补充专有变量。这样共性部分只维护一份,新增设备类型时继承即可,SCADA 侧也能按基类型统一做画面模板。

矿山设备 OPC UA 类型继承与实例化模型 MineEquipmentType(抽象基类型) 变量:DeviceID · RunState · FaultCode · Location 方法:Reset() 事件:GeneralFaultEvent HasSubtype 继承 BallMillType BearingTemp(℃, 0~85) MotorCurrent(A)· FeedRate(t/h) 方法:Start / Stop 事件:BearingOverheat SlurryPumpType OutletPressure(kPa) FlowRate(m³/h)· SealLeak 方法:Start / Stop 事件:DryRunAlarm BeltConveyorType BeltSpeed(m/s)· Deviation PullCordState · Blockage 方法:Start / Stop 事件:BeltTear HasTypeDefinition 实例化 BM-01 一段球磨机 BearingTemp = 62.4 ℃ RunState = Running BM-02 二段球磨机 BearingTemp = 71.8 ℃ RunState = Running P-07 尾矿渣浆泵 OutletPressure = 286 kPa RunState = Stopped 建模要点 ① 共性变量与方法上提到基类型,派生类型只补充专有量,避免重复定义; ② 变量必须携带 EngineeringUnits、EURange、AccessLevel,SCADA 才能自动生成量程与读写权限; ③ 实例通过 HasTypeDefinition 引用类型,类型修改后所有实例同步生效,实现“一次建模、多台复用”。

三、变量建模的关键属性不能省

很多初学者建模时只填了变量名和值,结果 SCADA 联调时发现量程要手工配、单位要手工填、写值被拒却查不出原因。问题就出在属性缺失。以球磨机主轴承温度为例,一个可用于工程的变量至少应定义如下属性:

NodeId:      ns=2;s=Plant1.BM01.BearingTemp
BrowseName:  2:BearingTemp
DisplayName: 主轴承温度
DataType:    Double
ValueRank:   Scalar
AccessLevel: CurrentRead
EngineeringUnits: {UnitId: 4408652, DisplayName: "°C"}
EURange:     {Low: 0.0, High: 85.0}
Historizing: true

其中 EURange 是工程量程,SCADA 用它自动生成趋势图纵轴和报警上下限的默认值;AccessLevel 设为只读,客户端写值时会直接收到 BadNotWritable,而不是“写了没反应”;Historizing 为真表示该变量支持历史数据访问,便于后续做趋势回放。这些属性不是可选项,而是信息模型能否被上位机“读懂”的关键。

四、方法建模:把设备动作也纳入模型

矿山设备的启停往往有严格的联锁条件,如果只把“启动”做成一个可写布尔变量,SCADA 侧无法表达“启动前需确认润滑就绪、无急停”这类逻辑。OPC UA 的方法正好承载这类语义。以 BallMillType.Start 为例,可定义输入参数 TargetSpeed(目标转速,Double,r/min)和输出参数 Result(Int32,0 成功、1 润滑未就绪、2 急停未复位)。服务端在方法回调中执行联锁判断,客户端调用后读取输出参数即可知道失败原因,比单纯读写布尔量更清晰、更可诊断。

五、事件建模:让设备主动“说话”

变量是轮询式的“我问你答”,事件则是设备主动上报的“我告诉你”。OPC UA 事件通过 EventNotifier 属性开启,客户端用订阅(Subscription)加监控项(MonitoredItem)接收。矿山场景中,轴承超温、皮带撕裂、泵干转都属于典型事件。建模时可自定义事件类型 BearingOverheatEventType,继承自标准 BaseEventType,并补充 Temperature、Threshold、DeviceId 等字段。这样 SCADA 收到事件后,不仅能弹出“BM-01 轴承超温”,还能直接显示“当前 88.2℃,阈值 85℃”,便于值班人员判断严重程度。

六、建模落地时的两个实用约定

第一,命名空间要规划好。标准节点放在 ns=0,厂商或项目自定义类型统一放在一个自定义命名空间(如 ns=2),并在服务器启动时注册 URI,避免不同项目合并时 NodeId 冲突。第二,NodeId 用字符串形式并带层级语义,例如 ns=2;s=Plant1.Area2.BM01.BearingTemp,比纯数字 NodeId 更利于排查和跨系统映射。建模完成后,务必用 UaExpert 之类的客户端实际浏览一遍地址空间,确认类型层级、变量属性、方法签名、事件字段都符合预期,再交给 SCADA 侧做画面与报警组态——这一步做扎实,后面的联调会省去大量返工。

建模自检清单:① 每台设备是否都通过 HasTypeDefinition 指向了正确的类型?② 所有模拟量变量是否都带 EngineeringUnits 与 EURange?③ 只读量的 AccessLevel 是否已限制?④ 方法是否定义了完整的输入输出参数?⑤ 关键事件类型是否补充了业务字段?五项全部通过,信息模型才具备被 SCADA 直接消费的条件。