如何在运行中的C# OPC UA Server动态添加节点?
OPC UA服务器运行时动态添加节点的实现方案
一、服务器端直接创建(推荐方案)
既然你是从MQTT、Socket这类外部进程获取数据,直接在服务器端处理比走客户端调用流程更高效,也更贴合OPC UA的架构逻辑。
实现步骤
- 监听MQTT/Socket的数据流,解析出节点关键信息:节点ID、显示名称、父节点ID、数据类型等
- 在自定义的
CustomNodeManager2实例中,调用内置API创建并添加节点 - 触发地址空间变更通知,让客户端能实时感知到新节点
代码示例
// 假设你的自定义节点管理器是MyNodeManager,已完成初始化 public void AddDynamicNode(string nodeIdStr, string displayName, NodeId parentNodeId, NodeId dataTypeId) { // 构建节点属性 var varAttrs = new VariableAttributes { DisplayName = new LocalizedText(displayName), Description = new LocalizedText("从外部数据源同步的动态节点"), AccessLevel = AccessLevels.CurrentRead | AccessLevels.CurrentWrite, UserAccessLevel = AccessLevels.CurrentRead | AccessLevels.CurrentWrite, DataType = dataTypeId, ValueRank = ValueRanks.Scalar, Historizing = false }; // 生成节点ID(注意命名空间索引要和你的节点管理器匹配) var newNodeId = new NodeId(nodeIdStr, MyNodeManager.NamespaceIndex); // 创建变量节点实例 var variableNode = new VariableNode( MyNodeManager.Server.DefaultNodeManager, newNodeId, new QualifiedName(displayName, MyNodeManager.NamespaceIndex), newNodeId, varAttrs); // 添加到地址空间 MyNodeManager.AddNode(variableNode); // 关联到父节点并触发变更通知 if (MyNodeManager.FindNode(parentNodeId) is BaseObjectNode parentNode) { parentNode.AddChild(variableNode); MyNodeManager.Server.FireNodeChangeNotification(new NodeChangeNotificationEventArgs(NodeChangeType.Added, variableNode)); } }
之后你只需要在MQTT的消息回调或者Socket的数据接收方法里,调用这个AddDynamicNode方法,传入解析好的参数即可。
二、客户端调用AddNodes()的正确姿势
如果你一定要用客户端方式添加节点,需要注意SessionClient的调用规范,同时确保服务器开启了相应权限。
代码示例
// 假设已成功建立OPC UA客户端会话 public async Task AddNodeThroughClient(SessionClient session, string nodeIdStr, string displayName, NodeId parentNodeId) { var addItem = new AddNodesItem { ParentNodeId = parentNodeId, ReferenceTypeId = ReferenceTypeIds.Organizes, RequestedNewNodeId = new NodeId(nodeIdStr, 2), // 替换为你的命名空间索引 BrowseName = new QualifiedName(displayName, 2), NodeClass = NodeClass.Variable, NodeAttributes = new VariableAttributes { DisplayName = new LocalizedText(displayName), DataType = DataTypeIds.Double, // 根据实际数据类型调整 AccessLevel = AccessLevels.CurrentRead, UserAccessLevel = AccessLevels.CurrentRead, ValueRank = ValueRanks.Scalar }, TypeDefinitionId = VariableTypeIds.BaseDataVariableType }; var request = new AddNodesRequest { NodesToAdd = new[] { addItem } }; try { var response = await session.AddNodesAsync(request); if (response.Results[0].StatusCode.IsGood()) { Console.WriteLine("节点添加成功"); } else { Console.WriteLine($"添加失败:{response.Results[0].StatusCode}"); } } catch (Exception ex) { Console.WriteLine($"添加出错:{ex.Message}"); } }
注意事项:
- 服务器配置中需开启
SecurityConfiguration.AllowModifyAddresses = true - 客户端会话必须拥有
Modify权限,否则会被服务器拒绝操作
三、可用辅助库
- Opc.Ua.Server:你正在使用的官方库,自带的API完全能满足需求,无需额外依赖
- MQTTnet:轻量级MQTT处理库,可快速实现MQTT客户端,接收数据后直接调用服务器端节点添加方法
- SocketAsyncEventArgs:.NET原生高效Socket处理类,适合高并发数据流场景
内容的提问来源于stack exchange,提问作者Choi0310
相关产品推荐
相关产品推荐

