基于OPC UA Foundation仓库的.NET服务器添加OnRead方法求助
解决OPC UA .NETStandard SampleServer动态处理Read请求并创建节点的问题
在OPC UA .NETStandard框架中,SampleServer及其父类没有直接暴露OnRead方法,但可以通过两种方式实现Read请求的拦截和动态节点创建:
方案一:在SampleServer中覆盖请求处理方法
直接在你的SampleServer类中重写ProcessRequestAsync,识别Read请求并处理缺失节点:
protected override async Task<IServiceResponse> ProcessRequestAsync(IServiceRequest request, RequestHeader requestHeader, Session session) { if (request is ReadRequest readRequest) { // 遍历所有待读取节点,检查是否存在 foreach (var nodeToRead in readRequest.NodesToRead) { var targetNodeId = nodeToRead.NodeId; if (!ServerCore.NodeManager.IsNodeIdKnown(targetNodeId)) { // 动态创建缺失的节点 await CreateDynamicNodeAsync(targetNodeId); } } } // 交给基类处理后续请求逻辑 return await base.ProcessRequestAsync(request, requestHeader, session); } // 动态创建节点的辅助方法 private async Task CreateDynamicNodeAsync(NodeId nodeId) { // 获取自定义的SampleNodeManager(根据你的实际类名调整) var sampleNodeManager = (SampleNodeManager)ServerCore.NodeManager; // 创建一个示例变量节点(可根据需求修改节点类型、数据类型等) var dynamicVariable = new VariableNode( sampleNodeManager, nodeId, new QualifiedName(nodeId.Identifier.ToString(), sampleNodeManager.NamespaceIndex), new LocalizedText("en-US", $"Dynamic Node: {nodeId.Identifier}"), null, new DataValue(0), // 初始值 NodeId.Parse("i=63"), // 数据类型:Int32 NodeId.Parse("i=63"), // 数据类型定义 NodeId.Parse("i=58") // 访问权限:可读可写 ); // 将节点添加到NodeManager await sampleNodeManager.AddNodeAsync(dynamicVariable); }
方案二:在自定义NodeManager中覆盖节点读取方法
如果你的业务逻辑更贴近节点管理,推荐在SampleNodeManager中重写ReadNodesAsync方法,直接在节点管理层面处理:
public override async Task<ReadResponseCollection> ReadNodesAsync(ReadContext context, ReadValueIdCollection nodesToRead, TimestampsToReturn timestampsToReturn) { // 预处理缺失节点 foreach (var nodeToRead in nodesToRead) { var targetNodeId = nodeToRead.NodeId; if (!IsNodeIdKnown(targetNodeId)) { await CreateDynamicNodeAsync(targetNodeId); } } // 调用基类完成读取操作 return await base.ReadNodesAsync(context, nodesToRead, timestampsToReturn); } // 动态创建节点的辅助方法 private async Task CreateDynamicNodeAsync(NodeId nodeId) { var dynamicVariable = new VariableNode( this, nodeId, new QualifiedName(nodeId.Identifier.ToString(), NamespaceIndex), new LocalizedText("en-US", $"Dynamic Node: {nodeId.Identifier}"), null, new DataValue(0), NodeId.Parse("i=63"), NodeId.Parse("i=63"), NodeId.Parse("i=58") ); await AddNodeAsync(dynamicVariable); }
关键说明
- 框架设计原因:OPC UA .NETStandard没有直接提供
OnRead钩子,而是通过服务请求处理、NodeManager节点管理的分层设计来扩展功能。 - 命名空间注意:确保动态节点的
NodeId命名空间索引与你的SampleNodeManager一致,否则会无法被正确管理。 - 节点类型扩展:上述示例创建的是变量节点,你可以根据需求修改为对象、方法等其他OPC UA节点类型。
内容的提问来源于stack exchange,提问作者StefanF00
相关产品推荐
相关产品推荐

