Skip to content

✨ 新增 OPC UA Client 通信协议 - #2

Merged
keeleycenc merged 1 commit into
mainfrom
feat/opcua-client
Jul 14, 2026
Merged

keeleycenc merged 1 commit into
mainfrom
feat/opcua-client

Conversation

@keeleycenc

Copy link
Copy Markdown
Collaborator

Pull Request 描述

首版将 MAS.Communication 扩展为支持 OPC UA Client。OPC UA 复用统一的 IProtocol 生命周期与 IProtocolManager 实例管理,但保持自己的“节点、会话、订阅、安全”模型,不抽象成 Modbus/MC 那样的地址读写接口,公共 API 也不泄漏官方 SDK 类型。

提交前检查

  • 本地合并了最新的代码,解决了合并冲突
  • 已经检查了代码,并在必要的位置添加了相应的注释
  • 遵循了此项目的代码风格及规范
  • 代码构建干净,没有任何错误和警告(net481/net8.0/net9.0/net10.0 均 0 警告 0 错误)
  • 已经添加单元测试(非必须)
  • 更新了相应的文档(非必须)

变更类型

  • 新功能
  • 文档内容更新

目的

问题描述:

  • 新增 OPC UA 客户端,作为工业通信框架的又一协议接入
  • 通过专属接口 IOpcUaProtocol 暴露业务能力,IOpcUaCommunicationConfig 提供配置
  • 覆盖首版范围:连接、单/批量读写、浏览、方法调用、数据变化订阅、KeepAlive 与自动重连

预期影响:

  • 纯新增能力,不改动现有 Modbus/MC/S7 的行为
  • 核心接入点为最小改动:CommProtocol 增加 OpcUa、ProtocolManager.CreateProtocol 与 CommunicationConfigExtensions.GetInstanceKey 各增加一个分支

主要内容

  • 接口:IOpcUaProtocol、IOpcUaCommunicationConfig、IOpcUaSubscription、IOpcUaCredentialProvider
  • 实现:OpcUaProtocolClient(生命周期映射 + KeepAlive + SessionReconnectHandler 自动重连)、OpcUaSubscription(内部队列派发,不阻塞 SDK Publish 流程)、OpcUaEndpointSelector / OpcUaCertificateManager / OpcUaValueConverter
  • 模型:OpcUaNodeId、OpcUaValue、OpcUaReadItem、OpcUaWriteItem、OpcUaWriteResult、OpcUaBrowseNode、OpcUaMethodResult、OpcUaMonitoredItem、OpcUaSubscriptionOptions、OpcUaUserCredential 及枚举
  • 异常:OpcUaServiceException(含 StatusCode/诊断信息)、OpcUaCertificateException
  • 安全:三种身份(匿名 / 用户名密码 / 客户端证书)与 None/Sign/SignAndEncrypt,严格证书校验(默认不自动接受不受信任证书)
  • 实例键:OpcUa|规范化EndpointUrl|SecurityMode|SecurityPolicyUri|IdentityType|IdentityId,不包含密码/凭据引用
  • 快照:配置在客户端创建时克隆为快照,避免调用方中途修改导致无法从缓存移除
  • 依赖:OPC Foundation 官方客户端 Core/Client/Configuration,通过 $(OpcUaVersion) 锁定统一版本(1.5.378.156);Microsoft.Extensions.DependencyInjection.Abstractions 升级到 10.0.8 以满足传递依赖
  • net481:新增 IsExternalInit 占位类型(src/Polyfills/CompilerPolyfills.cs)以支持 record/init
  • 文档:更新根 README.md、src/README.md、docs/index.md、docs/content/toc.yml,新增 docs/content/MAS.Communication.OpcUaProtocol.md

评估

性能影响:

  • 订阅通知先进入内部队列再由派发线程触发事件,避免用户业务处理阻塞 OPC UA 的 Publish 流程

兼容性问题:

  • 新增 CommProtocol.OpcUa 枚举项(追加在末尾,保持既有序号不变)
  • 无破坏性变更

测试

  • 单元测试(离线,共 23 项):模型状态码判定、值转换、实例键规则(含“密码不入键”“端点规范化”)、管理器创建/复用/快照/释放,全部通过
  • 集成测试(tests/OpcUaProtocol/OpcUaConnectionTest.cs,共 5 项):通过环境变量 MAS_OPCUA_ENDPOINT 指定端点,无法连接时标记 Inconclusive;已在本地 StandardServer 上验证 连接、单/泛型/批量读取(含部分失败逐项状态)、浏览、数据变化订阅 全部通过
  • 方法调用与自动重连未在真实服务端运行时验证(与已验证路径结构一致)

额外信息

  • 由于 1.5.378 版官方 SDK 将稳定的同步友好重载标记为过时(改用 ITelemetryContext 新 API),OPC UA 实现文件在文件作用域内针对性抑制了 CS0618,遥测 API 迁移暂不在首版范围
  • 本次改动顺带包含一处由项目自动格式化工具产生的无关简化:src/Helpers/StructBinaryHelper.cs 将 #if !NETFRAMEWORK 条件简化为 s[..attr.Length](在 net481 上同样可编译)

Copyright (c) MAS(厦门威光) Corporation. All rights reserved.

新增 OPC UA 客户端,复用统一的 IProtocol 生命周期与 IProtocolManager 实例管理,
但保持自己的“节点、会话、订阅、安全”模型,不抽象成地址读写接口,公共 API 也不泄漏
官方 SDK 类型。

主要内容:
- 新增 IOpcUaProtocol / IOpcUaCommunicationConfig / IOpcUaSubscription /
  IOpcUaCredentialProvider 接口,以及 OpcUaProtocolClient 实现
- 轻量模型:OpcUaNodeId、OpcUaValue、OpcUaWriteResult、OpcUaBrowseNode、
  OpcUaMethodResult、OpcUaMonitoredItem、OpcUaSubscriptionOptions 及相关枚举
- 单/批量读写(批量返回逐项状态)、浏览、方法调用、数据变化订阅、KeepAlive 与自动重连
- 安全:三种身份(匿名/用户名密码/客户端证书)与 None/Sign/SignAndEncrypt,
  严格证书校验;密码不进入实例键/日志/异常,经 CredentialKey + CredentialProvider 解析
- 配置在创建时克隆为快照;订阅通知经内部队列派发,不阻塞 SDK Publish 流程
- 接入 ProtocolManager 与 GetInstanceKey;依赖 OPC Foundation 官方客户端并锁定统一版本
- 为 net481 补充 IsExternalInit 占位类型以支持 record/init
- 补充根目录与 docs 文档,以及单元测试与集成测试

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@keeleycenc
keeleycenc merged commit dac17cc into main Jul 14, 2026
1 check passed
@keeleycenc
keeleycenc deleted the feat/opcua-client branch July 14, 2026 14:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant