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 { } } }
private bool Collect(ref Dictionary <int, Station> dicStations, out string errMsg) { errMsg = ""; if (dicStations == null) { errMsg = "无法采集空对象的站点组"; return(false); } foreach (int key in dicStations.Keys) { Station station = dicStations[key]; if (station.opc == null || !station.opc.IsOpcConnected) { TraceManagerForOPC.AppendWarning("StationName:" + station._StationName + "关联的OPCServer已经离线"); station.IsOnline = false; continue; } if (station.sensors == null || station.sensors.Count == 0) { TraceManagerForOPC.AppendWarning("StationName:" + station._StationName + "没有关联对应的sensor需要采集"); station.IsOnline = false; continue; } // 单点采集 int errorTimes = 0; // n个失败就不采集 int okayTimes = 0; // n个成功,就在线 string errPointIDs = ""; DateTime dt = DateTime.Now; foreach (Sensor sensor in dicStations[key].sensors) { sensor.LastTime = DataUtil.ToDateString(dt); // 防止采集的点多了,错误消息炸了,每个都报出来了---直接让机组离线 if (errorTimes >= Config.scadaConfig.errorTimes) { TraceManagerForOPC.AppendWarning(string.Format("站点名称:{0}-pointID列表:{1} 采集失败,已跳过该站点采集,可能原因:站点离线或者被禁用采集", station._StationName, errPointIDs)); station.IsOnline = false; break; } // 检查未通过 if (!sensor.CheckScadaOPC(out string err)) { sensor.MakeFail(sensor.sensorName + err); TraceManagerForOPC.AppendWarning(sensor.sensorName + "配置错误" + err); continue; } // 跳过忽略型 if (sensor.type == PointType.Ignore) { continue; } string opcItemName = OpcDaClient.GetTagName(station._FOPCServerName, station._FOPCDeviceName, sensor.offsetAddress, sensor.dataSourceAddress); // OPC 客户端缓存队列寻找该条目值 OpcTag tag = station.opc.GetTagByName(opcItemName, out string er); if (tag == null) { sensor.MakeFail(er); // 未找到tag TraceManagerForOPC.AppendErrMsg(er); // 未找到tag continue; } if (!string.IsNullOrEmpty(tag.Error)) { sensor.MakeFail(tag.Error); errorTimes++; errPointIDs += sensor.pointID.ToString() + " "; // TraceManagerForOPC.AppendWarning(string.Format("{0}-{1}采集失败,错误原因:{2}", station._StationName, sensor.sensorName, sensor.Mess)); continue; } if (tag.Value == null) { sensor.MakeFail(opcItemName + "取值失败"); errorTimes++; errPointIDs += sensor.pointID.ToString() + " "; // TraceManagerForOPC.AppendWarning(string.Format("{0}-{1}取值失败,错误原因:{2}", station._StationName, sensor.sensorName, sensor.Mess)); continue; } // 根据数据源获取数据 sensor.ReadOPCPoint(tag.Value); if (sensor.State == ValueState.Fail) { // TraceManagerForOPC.AppendWarning(string.Format("{0}-{1}采集失败,取值错误:{2}", station._StationName, sensor.sensorName, sensor.Mess)); errorTimes++; errPointIDs += sensor.pointID.ToString() + " "; continue; } else { okayTimes++; } } // 判断是否离线 if (okayTimes >= Config.scadaConfig.okayTimes) { station.IsOnline = true; } else { station.IsOnline = false; } AddOnLinePoint(station.IsOnline, ref station); //配置在线点就维护 } return(true); }
private bool Collect(ref List <PumpJZ> jzs, out string errMsg) { errMsg = ""; if (jzs == null) { errMsg = "无法采集空对象的机组"; return(false); } foreach (PumpJZ jz in jzs) { if (jz.opc == null || !jz.opc.IsOpcConnected) { TraceManagerForOPC.AppendWarning(jz.PName + jz.PumpJZArea + "关联的OPCServer已经离线"); jz.IsOnline = false; continue; } if (jz.points == null || jz.points.Length == 0) { TraceManagerForOPC.AppendWarning(jz.PName + jz.PumpJZArea + "没有关联对应版本的点表"); jz.IsOnline = false; continue; } // 加入离线、采集时间的点 string lastTime = DataUtil.ToDateString(DateTime.Now); Point pOnline = new Point() { dbSAddress = "FOnLine", Value = jz.IsOnline == true ? 1 : 0, State = ValueState.Success, LastTime = lastTime }; Point pTempTime = new Point() { dbSAddress = "TempTime", Value = lastTime, State = ValueState.Success, LastTime = lastTime }; // 单点采集 int errorTimes = 0; // n个失败就不采集 int okayTimes = 0; // n个成功,就在线 string errPointIDs = ""; foreach (Point point in jz.points) { // 防止采集的点多了,错误消息炸了,每个都报出来了---直接让机组离线 if (errorTimes >= Config.pumpConfig.errorTimes) { TraceManagerForOPC.AppendWarning(string.Format("{0}-{1}-pointID列表:{2}-采集失败,已跳过该机组采集,可能原因:机组离线或者被禁用采集", jz.PName, jz.PumpJZArea, errPointIDs)); jz.IsOnline = false; break; } // 检查未通过 if (!point.CheckPumpOPC(out string err)) { point.MakeFail(point.name + err); TraceManagerForOPC.AppendWarning(point.name + "配置错误" + err); continue; } string opcItemName = OpcDaClient.GetTagName(jz.FOPCServerName, jz.FOPCDeviceName, point.offsetAddress, point.dataSourceAddress); // OPC 客户端缓存队列寻找该条目值 OpcTag tag = jz.opc.GetTagByName(opcItemName, out string er); if (tag == null) { point.MakeFail(er); TraceManagerForOPC.AppendWarning(er); // 未找到tag continue; } if (!string.IsNullOrEmpty(tag.Error)) { point.MakeFail(tag.Error); errorTimes++; errPointIDs += point.pointID.ToString() + " "; // TraceManagerForOPC.AppendWarning(string.Format("{0}-{1}-{2}采集失败,错误原因:{3}", jz.PName, jz.PumpJZArea, point.name, point.Mess)); continue; } if (tag.Value == null) { point.MakeFail(opcItemName + "取值失败"); errorTimes++; errPointIDs += point.pointID.ToString() + " "; // TraceManagerForOPC.AppendWarning(string.Format("{0}-{1}-{2}取值失败,错误原因:{3}", jz.PName, jz.PumpJZArea, point.name, point.Mess)); continue; } // 根据数据源获取数据 point.ReadOPCPoint(tag.Value); if (point.State == ValueState.Fail) { // TraceManagerForOPC.AppendWarning(string.Format("{0}-{1}-{2}采集失败,取值错误:{3}", jz.PName, jz.PumpJZArea, point.name, point.Mess)); errorTimes++; errPointIDs += point.pointID.ToString() + " "; continue; } else { okayTimes++; } } // 判断是否离线 if (okayTimes >= Config.pumpConfig.okayTimes) { jz.IsOnline = true; } else { jz.IsOnline = false; } // 附加离线、时间点 if (jz.IsOnline) { pOnline.Value = 1; } else { pOnline.Value = 0; } List <Point> points = new List <Point>(); points.AddRange(new Point[] { pOnline, pTempTime }); points.AddRange(jz.points); jz.points = points.ToArray(); } return(true); }
// 枚举 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); }