设备通信与协议编程(十一):OPC UA 信息模型、订阅与互操作边界

串口、Modbus 和厂商 TCP 协议主要解决“如何交换字段”,OPC UA 更进一步:设备把对象、变量、方法、事件和它们之间的关系组织为可浏览的信息模型,客户端通过标准服务访问。

OPC UA 不是一个简单的“统一寄存器协议”。真正的互操作来自一致的信息模型、profile、安全配置和语义约定。

1. AddressSpace 是带类型的图

服务器向客户端暴露的 AddressSpace 由 Node 构成,Node 通过 Reference 相连。常见 NodeClass 包括 Object、Variable、Method、ObjectType、VariableType、ReferenceType 和 DataType。

1
2
3
4
5
Machine (Object)
├── State (Variable)
├── Temperature (Variable)
├── Start (Method)
└── Alarm (Event source)

Variable 不只是值,还可带 DataType、ValueRank、AccessLevel、工程单位、量程和时间戳。客户端应读取并验证这些元数据,而不是只把所有值转成字符串。

2. NodeId、BrowseName 与 DisplayName

标识用途稳定性注意
NodeId在服务器 AddressSpace 中标识 Nodenamespace index 可能随配置变化
ExpandedNodeId可携带 namespace URI 和 server index更适合跨地址空间表达
BrowseName浏览路径中的限定名不保证全局唯一
DisplayName面向用户的本地化文本不应作为程序主键

客户端配置应优先保存 namespace URI 与标识符的组合,并在连接后解析当前 namespace index。把 ns=2;s=Machine.State 永久写死,服务器新增 namespace 后可能指向错误模型。

3. 类型模型带来的价值

ObjectType 和 VariableType 允许服务器声明设备类型及其实例结构。Companion Specification 则为机器人、分析仪器、机床等领域定义共同语义。

互操作的层次可分为:

  1. 能建立安全连接;
  2. 能调用 Read、Write、Browse 等服务;
  3. 能理解相同 DataType 与单位;
  4. 能识别相同设备类型、状态和方法语义。

只达到前两层,往往仍需要项目级点表和适配代码。

4. 从发现到会话

客户端通常经历:

1
2
3
发现服务器/端点 → 选择 Endpoint 与安全策略
→ 建立 SecureChannel → 创建并激活 Session
→ 浏览、读写、调用或创建订阅

Endpoint 描述安全模式、SecurityPolicy、传输 profile 和用户令牌类型。客户端不能仅按 URL 选第一个端点,也不能为了“先连上”自动信任未知证书。

SecureChannel 保护消息通道;Session 管理客户端与服务器的逻辑交互上下文。两者生命周期相关但不是同一个概念。

5. Read/Write 的质量与时间戳

读取 Variable 得到的 DataValue 可包含:

  • Value;
  • StatusCode;
  • SourceTimestamp;
  • ServerTimestamp。

显示数值前先判断 StatusCode。GoodUncertainBad 表达数据质量;一个缓存的旧值即使类型正确,也不应被当成当前可信测量。

SourceTimestamp 表示数据源产生值的时间,ServerTimestamp 表示服务器处理该值的时间;具体提供哪些字段取决于服务器与请求参数。

6. MonitoredItem 与 Subscription

客户端创建 MonitoredItem 监视 Variable 的值变化或 Object 的事件,再把它们归入 Subscription。几个周期不能混为一谈:

参数含义
SamplingInterval服务器对 MonitoredItem 采样的请求间隔
PublishingIntervalSubscription 尝试发布 NotificationMessage 的周期
QueueSizeMonitoredItem 可缓存的通知数量
DiscardOldest队列满时丢旧值还是拒绝新值
KeepAlive/Lifetime无通知和通信中断时维持订阅的机制

服务器可根据能力修订请求值,客户端必须读取 revised 值。采样 10 ms、发布 100 ms 可能在一次 NotificationMessage 中携带多个变化;QueueSize 为 1 则只保留一个候选通知,不能还原全部中间过程。

7. 确认、重发与数据不丢失的边界

客户端通过 Publish 请求接收 NotificationMessage 并确认序列号;在服务器重传队列仍保留消息时,可用 Republish 请求缺失消息。普通订阅能跨越短暂通信中断,但可靠性受 Subscription lifetime、MonitoredItem 队列和重传队列限制。

OPC UA Part 4 还定义了可选的 durable Subscription 能力,用于更长中断甚至服务器重启场景。客户端必须先确认服务器 profile 和能力,不能假设所有服务器都支持持久订阅。

8. Deadband 与数据量

DataChangeFilter 可按状态、值或时间戳触发;Deadband 可减少微小变化通知。但设置前要确认:

  • 数据类型是否支持相应 deadband;
  • 百分比 deadband 依赖 EURange;
  • 过滤发生在服务器侧,不等于改变设备采样;
  • 报警、审计和控制反馈不能因错误过滤而丢失关键变化。

订阅不是“越快越好”。应按变量变化速度、业务延迟、服务器资源和网络预算分组。

9. 安全配置

生产客户端至少应做到:

  • 选择满足组织要求且双方均支持的 MessageSecurityMode 与 SecurityPolicy;避免规范已标记为过时的 Basic128Rsa15 和 Basic256,并根据服务器 profile 与组织要求在 Basic256Sha256、Aes128_Sha256_RsaOaep、Aes256_Sha256_RsaPss 等未过时策略中选择,而不是硬编码一个通用“基线”;
  • 验证服务器应用证书、主机名/应用 URI、有效期和信任链;
  • 将首次信任作为受控部署步骤,而不是运行时自动接受;
  • 使用最小权限的用户身份;
  • 管理证书续期、吊销列表与私钥权限;
  • 禁止将测试环境的匿名或 None 策略直接复制到生产。

OPC UA 的安全能力需要正确配置才能生效。网络隔离仍有价值,但不能替代端点身份验证和权限控制。

10. Client/Server 与 PubSub

本文讨论的是 Client/Server 模型:客户端主动建立 Session,调用服务并维护 Subscription。OPC UA PubSub 是另一套发布/订阅模型,可通过不同消息映射分发 DataSet,不使用同样的 Session/MonitoredItem 关系。

选择时考虑拓扑、发现、安全、可靠性和实时需求,而不是因为两者都叫“订阅”就混用配置概念。

11. C# 接入策略

OPC Foundation 维护 OPC UA .NET Standard 开源栈。生产接入时应固定经过验证的包版本,并在升级时回归:

  • Endpoint 选择与证书验证;
  • 自定义 DataType 编解码;
  • Session 重连与 Subscription 转移/重建;
  • revised 采样和发布参数;
  • 序列号缺口、Republish 与数据质量;
  • 服务器限制和 profile 差异。

将 SDK 封装在适配层,向业务暴露类型化设备能力和带质量的状态快照,不要让 ViewModel 到处持有 NodeId 和 SDK Session。

12. 小结

OPC UA 的核心不是“能读一个点”,而是用标准 AddressSpace、类型和服务表达设备语义。客户端必须正确处理 Node 标识、DataValue 质量、订阅队列、安全端点和服务器能力;只有模型语义也达成一致,连接成功才会变成真正的互操作。

参考资料

Licensed under CC BY-NC-SA 4.0