串口、Modbus 和厂商 TCP 协议主要解决“如何交换字段”,OPC UA 更进一步:设备把对象、变量、方法、事件和它们之间的关系组织为可浏览的信息模型,客户端通过标准服务访问。
OPC UA 不是一个简单的“统一寄存器协议”。真正的互操作来自一致的信息模型、profile、安全配置和语义约定。
1. AddressSpace 是带类型的图
服务器向客户端暴露的 AddressSpace 由 Node 构成,Node 通过 Reference 相连。常见 NodeClass 包括 Object、Variable、Method、ObjectType、VariableType、ReferenceType 和 DataType。
| |
Variable 不只是值,还可带 DataType、ValueRank、AccessLevel、工程单位、量程和时间戳。客户端应读取并验证这些元数据,而不是只把所有值转成字符串。
2. NodeId、BrowseName 与 DisplayName
| 标识 | 用途 | 稳定性注意 |
|---|---|---|
| NodeId | 在服务器 AddressSpace 中标识 Node | namespace index 可能随配置变化 |
| ExpandedNodeId | 可携带 namespace URI 和 server index | 更适合跨地址空间表达 |
| BrowseName | 浏览路径中的限定名 | 不保证全局唯一 |
| DisplayName | 面向用户的本地化文本 | 不应作为程序主键 |
客户端配置应优先保存 namespace URI 与标识符的组合,并在连接后解析当前 namespace index。把 ns=2;s=Machine.State 永久写死,服务器新增 namespace 后可能指向错误模型。
3. 类型模型带来的价值
ObjectType 和 VariableType 允许服务器声明设备类型及其实例结构。Companion Specification 则为机器人、分析仪器、机床等领域定义共同语义。
互操作的层次可分为:
- 能建立安全连接;
- 能调用 Read、Write、Browse 等服务;
- 能理解相同 DataType 与单位;
- 能识别相同设备类型、状态和方法语义。
只达到前两层,往往仍需要项目级点表和适配代码。
4. 从发现到会话
客户端通常经历:
| |
Endpoint 描述安全模式、SecurityPolicy、传输 profile 和用户令牌类型。客户端不能仅按 URL 选第一个端点,也不能为了“先连上”自动信任未知证书。
SecureChannel 保护消息通道;Session 管理客户端与服务器的逻辑交互上下文。两者生命周期相关但不是同一个概念。
5. Read/Write 的质量与时间戳
读取 Variable 得到的 DataValue 可包含:
- Value;
- StatusCode;
- SourceTimestamp;
- ServerTimestamp。
显示数值前先判断 StatusCode。Good、Uncertain 和 Bad 表达数据质量;一个缓存的旧值即使类型正确,也不应被当成当前可信测量。
SourceTimestamp 表示数据源产生值的时间,ServerTimestamp 表示服务器处理该值的时间;具体提供哪些字段取决于服务器与请求参数。
6. MonitoredItem 与 Subscription
客户端创建 MonitoredItem 监视 Variable 的值变化或 Object 的事件,再把它们归入 Subscription。几个周期不能混为一谈:
| 参数 | 含义 |
|---|---|
| SamplingInterval | 服务器对 MonitoredItem 采样的请求间隔 |
| PublishingInterval | Subscription 尝试发布 NotificationMessage 的周期 |
| QueueSize | MonitoredItem 可缓存的通知数量 |
| 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 质量、订阅队列、安全端点和服务器能力;只有模型语义也达成一致,连接成功才会变成真正的互操作。