2. OPC UA 基础架构:客户端/服务器模型、地址空间与节点引用
OPC UA 的核心设计围绕客户端/服务器(C/S)模型展开,并通过地址空间(AddressSpace)将工业现场数据组织成可遍历的节点网络。理解这三层结构是配置仪表盘和查询历史数据的前提。
2.1 客户端/服务器模型
OPC UA 采用非对称的 C/S 架构:服务器负责暴露数据与元数据,客户端负责发起请求与订阅。两者通过会话(Session)和通道(Channel)建立安全通信。
| 角色 | 职责 | 典型实例 |
|---|---|---|
| OPC UA 服务器 | 托管地址空间、管理节点、处理读写/订阅/历史请求 | PLC、DCS、SCADA、边缘网关 |
| OPC UA 客户端 | 发现服务器、浏览地址空间、读写变量、订阅数据变化 | HMI、仪表盘、MES、云端应用 |
关键点:一个服务器可同时服务多个客户端;一个客户端也可连接多个服务器。仪表盘通常作为客户端,同时采集多台 PLC 或网关的数据。
2.2 地址空间(AddressSpace)
地址空间是 OPC UA 服务器的核心数据组织方式,它将所有可访问的信息(变量、方法、对象、类型)组织成一个分层的、可遍历的图结构。地址空间由节点(Node)和引用(Reference)构成。
类比:地址空间就像工业现场的“文件系统”——节点是文件和文件夹,引用是目录结构中的链接关系。客户端通过“浏览”地址空间来发现数据。
2.2.1 节点(Node)
节点是地址空间的基本单元。每个节点都有一个唯一的 NodeId(数字、字符串或 GUID),并包含一组属性。OPC UA 定义了 8 种节点类(NodeClass):
| 节点类 | 用途 | 仪表盘关注度 |
|---|---|---|
| Object | 代表物理或逻辑对象(如电机、泵、控制器) | ⭐⭐⭐ |
| Variable | 存储数值或状态(如温度、压力、转速) | ⭐⭐⭐⭐⭐ |
| Method | 可调用的函数(如复位、启动) | ⭐⭐ |
| ObjectType | 对象的类型定义(如“电机类型”) | ⭐⭐ |
| VariableType | 变量的类型定义(如“模拟量类型”) | ⭐ |
| DataType | 数据类型定义(如 Int32、Float、String) | ⭐ |
| ReferenceType | 引用关系的类型定义(如“包含”、“连接”) | ⭐ |
| View | 地址空间的子集视图 | ⭐⭐ |
实战注意:仪表盘配置时,90% 的交互集中在 Variable 节点上。你需要关注变量的 DataType(数据类型)、AccessLevel(读写权限)和 Historizing(是否启用历史记录)。
2.2.2 引用(Reference)
引用是连接两个节点的有向边,定义了节点之间的语义关系。引用使得地址空间从“平面列表”变成“图结构”。常见的引用类型包括:
- Organizes:组织关系,用于构建层级树(如文件夹包含子文件夹)
- HasComponent:组成关系,对象包含子对象或变量
- HasProperty:属性关系,变量或对象拥有属性节点
- HasTypeDefinition:类型定义关系,指向节点的类型
- HasSubType:继承关系,类型之间的派生
2.3 地址空间浏览与仪表盘配置
在仪表盘配置阶段,客户端通过以下步骤获取数据:
- 发现服务器:通过 DiscoveryUrl 找到目标 OPC UA 服务器
- 建立安全通道:协商加密方式与身份认证
- 浏览地址空间:从 Root 节点开始,沿 Organizes / HasComponent 引用遍历
- 定位变量节点:找到需要采集的 Variable 节点,记录其 NodeId
- 读取属性:获取 DataType、AccessLevel、Historizing 等元数据
- 订阅或查询:对变量节点发起数据订阅或历史数据查询
实战技巧:使用 UA Expert 或 Prosys OPC UA Browser 工具,可以可视化浏览地址空间。在仪表盘配置界面中,通常提供“浏览树”组件,让用户通过点击展开节点来选取变量,无需手动输入 NodeId。
2.4 历史数据查询的基础
历史数据查询依赖于地址空间中的两个关键配置:
- Historizing 属性:Variable 节点上的布尔属性,为
true表示该变量启用了历史记录 - 历史服务器能力:服务器必须支持
HistoryRead服务,并提供历史存储后端(如内存环形缓冲区、SQL 数据库或时序数据库)
查询时,客户端构造 HistoryReadDetails 参数,指定起始时间、结束时间、聚合方式(如平均值、最小值、最大值)和采样间隔。
// 历史数据查询请求示例(伪代码)
HistoryReadRequest request = new HistoryReadRequest();
request.NodeId = "ns=2;s=Reactor.Temperature";
request.StartTime = "2025-01-01T00:00:00Z";
request.EndTime = "2025-01-02T00:00:00Z";
request.AggregateType = AggregateType.Average; // 平均值聚合
request.ProcessingInterval = 60000; // 1 分钟间隔
仪表盘集成:在配置历史趋势图时,你需要选择启用了 Historizing 的变量节点,并指定时间范围和聚合方式。服务器会返回时间戳-数值对数组,前端图表库(如 ECharts、Chart.js)直接渲染即可。