// 任务分发口 public void ExcuteCollect() { try { if (!ExcuteCollectHandle(out string errMsg)) { TraceManagerForOPC.AppendWarning("站点定时采集任务执行失败;" + errMsg); } } catch (Exception e) { TraceManagerForOPC.AppendErrMsg("站点定时采集任务执行失败--" + e.Message + "堆栈:" + e.StackTrace); } }
// 任务执行口--并附带超时功能 public void Excute() { ActionTimeout timeoutObj = new ActionTimeout(); try { switch (this.type) { case StationCommandType.Collect: { if (opcCommandType == OPCCommandType.Cancle) //已经在调度被标记放弃了,干要紧的任务 { return; } timeoutObj.Do = ExcuteCollect; bool bo = timeoutObj.DoWithTimeout(new TimeSpan(0, 0, 0, Config.scadaConfig.commandTimeoutSeconds)); if (bo) { TraceManagerForOPC.AppendWarning("站点定时采集任务执行超时"); GC.Collect(); } } break; case StationCommandType.Write: { timeoutObj.Do = ExcuteWrite; bool bo = timeoutObj.DoWithTimeout(new TimeSpan(0, 0, 0, Config.scadaConfig.commandTimeoutSeconds)); if (bo) { CommandManager.MakeTimeout("sensorID:" + requestCommand.sensorID + "执行写值命令超时", ref requestCommand); CommandManager.CompleteCommand(requestCommand); TraceManagerForCommand.AppendWarning(requestCommand.message); GC.Collect(); } } break; case StationCommandType.Reload: { timeoutObj.Do = ExcuteReload; bool bo = timeoutObj.DoWithTimeout(new TimeSpan(0, 0, 0, Config.scadaConfig.commandTimeoutSeconds)); if (bo) { CommandManager.MakeTimeout("执行重载站点数据命令超时", ref requestCommand); CommandManager.CompleteCommand(requestCommand); TraceManagerForCommand.AppendWarning(requestCommand.message); GC.Collect(); } } break; default: TraceManagerForOPC.AppendWarning("未知的站点OPC命令类型,无法执行"); return; } } catch (Exception e) { TraceManagerForOPC.AppendErrMsg("执行站点OPC任务失败,未知的任务类型:" + e.Message + "堆栈:" + e.StackTrace); } }
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 LoadCache(out Dictionary <int, Station> dicStations, out string err) { err = ""; dicStations = new Dictionary <int, Station>(); #region 查询sensor表 string sqlSensors = @"select x.*,x1.ID pointID ,x1.* from( select t.ID stationID,t.Name StationName ,t.FOPCDeviceName ,t.FOPCServerName,t.FPLCIP, t1.ID sensorID,t1.Name sensorName,t1.PointAddressID from SCADA_Station t ,SCADA_Sensor t1 where t.ID=t1.StationID and t.ReadMode='OPC' and (t.是否删除=0 or t.是否删除 is null ) and (t1.是否删除=0 or t1.是否删除 is null )) x left join PointAddressEntry x1 on x.PointAddressID=x1.ID and x1.是否激活=1;"; DataTable dtSensors = DBUtil.ExecuteDataTable(sqlSensors, out string errMsg); if (!string.IsNullOrWhiteSpace(errMsg)) { err = "查询sensor列表失败:" + errMsg; return(false); } foreach (DataRow dr in dtSensors.Rows) { Station station = new Station() { _ID = DataUtil.ToInt(dr["stationID"]), _StationName = DataUtil.ToString(dr["StationName"]), _FOPCDeviceName = DataUtil.ToString(dr["FOPCDeviceName"]), _FOPCServerName = DataUtil.ToString(dr["FOPCServerName"]), _FPLCIP = DataUtil.ToString(dr["FPLCIP"]), sensors = new List <Sensor>() }; Sensor sensor = new Sensor() { pointID = DataUtil.ToInt(dr["pointID"]), sensorID = DataUtil.ToString(dr["sensorID"]), sensorName = DataUtil.ToString(dr["sensorName"]), _PointAddressID = DataUtil.ToInt(dr["PointAddressID"]), versionID = DataUtil.ToInt(dr["版本ID"]), dataSourceAddress = DataUtil.ToString(dr["数据源地址"]).Trim(), offsetAddress = DataUtil.ToString(dr["偏移地址"]).Trim(), type = Point.ToType(DataUtil.ToString(dr["数据类型"])), isActive = DataUtil.ToInt(dr["是否激活"]), isWrite = DataUtil.ToInt(dr["是否写入"]), scale = DataUtil.ToDouble(dr["倍率"]) }; // 站点-sensor入字典库 if (dicStations.Keys.Contains(station._ID)) { dicStations[station._ID].sensors.Add(sensor); } else { station.sensors.Add(sensor); station.opc = this.opcClientManager.GetOPCClient(station._FOPCServerName); // 将站点的OPC对象赋值 if (station.Check(out errMsg)) { dicStations.Add(station._ID, station); } else { TraceManagerForOPC.AppendWarning("StationID:" + station._ID + "环境异常:" + errMsg); } } } if (dicStations.Keys.Count == 0) { err = "站点表明细没有关于OPC的站点表"; return(false); } #endregion 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); }
private bool LoadCache(out List <PumpJZ> jzs, out string err) { err = ""; jzs = null; Dictionary <int, List <Point> > pointsCache = new Dictionary <int, List <Point> >(); #region 查询点表 string sqlPoints = @"select t.*,t1.数据业务地址,t1.名称 from PointAddressEntry t,PumpPointAddressDetail t1 where t.点明细ID=t1.ID and t.是否激活=1 and t.版本ID in(select distinct PointAddressID from PumpJZ x,pump x1 where PumpJZReadMode='OPC' and (x.是否删除=0 or x.是否删除 is null) and (x1.是否删除=0 or x1.是否删除 is null));"; DataTable dtPoints = DBUtil.ExecuteDataTable(sqlPoints, out string errMsg); if (!string.IsNullOrWhiteSpace(errMsg)) { err = "查询二供点表版本失败:" + errMsg; return(false); } foreach (DataRow dr in dtPoints.Rows) { int versionID = DataUtil.ToInt(dr["版本ID"]); Point point = new Point() { pointID = DataUtil.ToInt(dr["ID"]), versionID = versionID, name = DataUtil.ToString(dr["名称"]), dataSourceAddress = DataUtil.ToString(dr["数据源地址"]).Trim(), offsetAddress = DataUtil.ToString(dr["偏移地址"]), dbSAddress = DataUtil.ToString(dr["数据业务地址"]).Trim(), type = Point.ToType(DataUtil.ToString(dr["数据类型"])), isActive = DataUtil.ToInt(dr["是否激活"]), isWrite = DataUtil.ToInt(dr["是否写入"]), scale = DataUtil.ToDouble(dr["倍率"]) }; if (pointsCache.Keys.Contains(versionID)) { pointsCache[versionID].Add(point); } else { pointsCache.Add(versionID, new List <Point>() { point }); } } if (pointsCache.Keys.Count == 0) { err = "点表明细没有关于OPC的点表"; return(false); } #endregion jzs = new List <PumpJZ>(); #region 查询JZ表 string sqlJZ = @"select CONVERT(varchar(50),t.ID) as BASEID ,t.PointAddressID,t.PumpJZArea,t.FOPCDeviceName ,t.FOPCServerName,t.FPLCIP, t1.PName from PumpJZ t,Pump t1 where t.PumpId=t1.ID and (t.是否删除=0 or t.是否删除 is null) and (t1.是否删除=0 or t1.是否删除 is null) and t.PumpJZReadMode='OPC' ;"; DataTable dtJZIDs = DBUtil.ExecuteDataTable(sqlJZ, out errMsg); if (!string.IsNullOrWhiteSpace(errMsg)) { err = "查询二供机组ID列表失败:" + errMsg; return(false); } foreach (DataRow dr in dtJZIDs.Rows) { int versionID = DataUtil.ToInt(dr["PointAddressID"]); if (!pointsCache.Keys.Contains(versionID)) { TraceManagerForOPC.AppendWarning("没有点表版本ID=" + versionID.ToString() + "的点表"); continue;// 此机组不采集,其他的正常采集 } List <Point> points = pointsCache[versionID]; // 准备点表 Point[] pointsCopy = ByteUtil.DeepClone <List <Point> >(points).ToArray();// 一定要深度辅助一个副本,防止引用类型 PumpJZ jz = new PumpJZ() { ID = DataUtil.ToString(dr["BASEID"]), PointAddressID = versionID, PName = DataUtil.ToString(dr["PName"]), PumpJZArea = DataUtil.ToString(dr["PumpJZArea"]), FOPCDeviceName = DataUtil.ToString(dr["FOPCDeviceName"]), FOPCServerName = DataUtil.ToString(dr["FOPCServerName"]), points = pointsCopy }; // jz加入OPC客户端对象 jz.opc = this.opcClientManager.GetOPCClient(jz.FOPCServerName); if (jz.Check(out errMsg)) { jzs.Add(jz); } else { TraceManagerForOPC.AppendWarning("PumpJZID:" + jz.ID + "环境异常:" + errMsg); } } #endregion return(true);; }