private void UpdateVariableValue() { Task.Run(() => { while (true) { try { int count = 0; if (count > 0 && count != cfgCount) { cfgCount = count; List <OpcuaNode> nodes = new List <OpcuaNode>(); UpdateNodesAttribute(nodes); } BaseDataVariableState node = null; foreach (var item in _nodeDic) { node = item.Value; node.Value = RandomLibrary.GetRandomInt(0, 99); node.Timestamp = DateTime.Now; node.ClearChangeMasks(SystemContext, false); } Thread.Sleep(1000 * 1); } catch (Exception ex) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("更新OPC-UA节点数据触发异常:" + ex.Message); Console.ResetColor(); } } }); }
/// <summary> /// 实时更新节点数据 /// </summary> public void UpdateVariableValue() { Task.Run(() => { while (true) { try { /* * 此处仅作示例代码 所以不修改节点树 故将UpdateNodesAttribute()方法跳过 * 在实际业务中 请根据自身的业务需求决定何时修改节点菜单树 */ int count = 0; //配置发生更改时,重新生成节点树 if (count > 0 && count != cfgCount) { cfgCount = count; List <OpcuaNode> nodes = new List <OpcuaNode>(); /* * 此处有想过删除整个菜单树,然后重建 保证各个NodeId仍与原来的一直 * 但是 后来发现这样会导致原来的客户端订阅信息丢失 无法获取订阅数据 * 所以 只能一级级的检查节点 然后修改属性 */ UpdateNodesAttribute(nodes); } //模拟获取实时数据 BaseDataVariableState node = null; /* * 在实际业务中应该是根据对应的标识来更新固定节点的数据 * 这里 我偷个懒 全部测点都更新为一个新的随机数 */ foreach (var item in _nodeDic) { node = item.Value; node.Value = RandomLibrary.GetRandomInt(0, 99); node.Timestamp = DateTime.Now; //变更标识 只有执行了这一步,订阅的客户端才会收到新的数据 node.ClearChangeMasks(SystemContext, false); } //1秒更新一次 Thread.Sleep(1000 * 1); } catch (Exception ex) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("更新OPC-UA节点数据触发异常:" + ex.Message); Console.ResetColor(); } } }); }