private void OnDataChange(int TransactionID, int NumItems, ref Array clientHandles, ref Array itemValues, ref Array qualities, ref Array timeStamps) { // 服务端异常退出后, 可能还会有残留的回调, 丢弃 if (!_isOpcConnected) { return; } for (int i = 1; i < NumItems + 1; i++) { try { int clientHandle = Convert.ToInt32(clientHandles.GetValue(i)); OpcTag opcTag = null; lock (_tagClientHandleIndex) _tagClientHandleIndex.TryGetValue(clientHandle, out opcTag); if (opcTag == null) { continue; } object value = itemValues.GetValue(i); int quality = Convert.ToInt32(qualities.GetValue(i)); DateTime timeStamp = Convert.ToDateTime(timeStamps.GetValue(i)); opcTag.Set(value, quality, timeStamp); } catch { } } }
// 枚举 OPC 服务器中所有标签 private void BuildGroupsAndTags() { _client.OPCGroups.DefaultGroupIsActive = true; _client.OPCGroups.DefaultGroupDeadband = _defaultGroupDeadband; _client.OPCGroups.DefaultGroupUpdateRate = _updateRate; // 准备批量创建节点 List <string> listItemIds = new List <string>(); List <int> listClientHandles = new List <int>(); int itemHandle = 1; int itemCount = 0; // 批量创建时, 数组标号从 1 开始, 0 位无用 listItemIds.Add(""); listClientHandles.Add(0); // 枚举节点 OPCBrowser opcBrowser = _client.CreateBrowser(); opcBrowser.ShowBranches(); opcBrowser.ShowLeafs(true); foreach (object turn in opcBrowser) { string name = turn.ToString(); if (string.IsNullOrEmpty(name)) { continue; } // 过滤系统变量 if (name.StartsWith("_") || name.IndexOf("._") > 0) { continue; } listItemIds.Add(name); listClientHandles.Add(itemHandle++); itemCount++; } // 创建组和节点 _group = _client.OPCGroups.Add("RootGroup"); Array itemIds = listItemIds.ToArray(); Array clientHandles = listClientHandles.ToArray(); _group.OPCItems.AddItems(itemCount, ref itemIds, ref clientHandles, out Array serverHandles, out Array errors); // 创建标签 for (int i = 1; i < itemCount + 1; i++) { string itemName = Convert.ToString(itemIds.GetValue(i)); int clientHandle = Convert.ToInt32(clientHandles.GetValue(i)); int serverHandle = Convert.ToInt32(serverHandles.GetValue(i)); OpcTag opcTag = new OpcTag(itemName, clientHandle, serverHandle); lock (_tagNamedIndex) _tagNamedIndex[itemName] = opcTag; lock (_tagClientHandleIndex) _tagClientHandleIndex[clientHandle] = opcTag; lock (_tagServerHandleIndex) _tagServerHandleIndex[serverHandle] = opcTag; } // 启用订阅 _group.IsSubscribed = true; _group.DataChange += OnDataChange; // 从客户端缓存读取一次, 获取初始值 itemCount = _group.OPCItems.Count; _group.SyncRead((short)OPCDataSource.OPCCache, itemCount, ref serverHandles, out Array values, out errors, out object qualities, out object timeStamps); for (int i = 1; i < itemCount + 1; i++) { int serverHandle = Convert.ToInt32(serverHandles.GetValue(i)); OpcTag opcTag = null; lock (_tagServerHandleIndex) _tagServerHandleIndex.TryGetValue(serverHandle, out opcTag); if (opcTag == null) { continue; } object value = values.GetValue(i); int quality = Convert.ToInt32(((Array)qualities).GetValue(i)); DateTime timeStamp = Convert.ToDateTime(((Array)timeStamps).GetValue(i)); opcTag.Set(value, quality, timeStamp); } // 从设备异步读取一次 _group.AsyncRefresh((short)OPCDataSource.OPCDevice, 1001, out int cancelId); }